<?xml version="1.0"?><?xml-stylesheet type="text/xsl" href="/rss.xsl"?><rss version="2.0"><channel><title>HL2GLSL</title><link>http://hl2glsl.codeplex.com/project/feeds/rss</link><description>High Level Shading Language to OpengGL Shading Language translator</description><item><title>Source code checked in, #94877</title><link>http://hl2glsl.codeplex.com/SourceControl/changeset/changes/94877</link><description>Upgrade&amp;#58; New Version of LabDefaultTemplate.xaml. To upgrade your build definitions, please visit the following link&amp;#58; http&amp;#58;&amp;#47;&amp;#47;go.microsoft.com&amp;#47;fwlink&amp;#47;&amp;#63;LinkId&amp;#61;254563</description><author>Project Collection Service Accounts</author><pubDate>Mon, 01 Oct 2012 22:38:35 GMT</pubDate><guid isPermaLink="false">Source code checked in, #94877 20121001103835P</guid></item><item><title>Source code checked in, #94876</title><link>http://hl2glsl.codeplex.com/SourceControl/changeset/changes/94876</link><description>Checked in by server upgrade</description><author>Project Collection Service Accounts</author><pubDate>Mon, 01 Oct 2012 22:31:06 GMT</pubDate><guid isPermaLink="false">Source code checked in, #94876 20121001103106P</guid></item><item><title>Source code checked in, #57274</title><link>http://hl2glsl.codeplex.com/SourceControl/changeset/changes/57274</link><description>Checked in by server upgrade</description><author>_TFSSERVICE</author><pubDate>Wed, 28 Jul 2010 22:13:23 GMT</pubDate><guid isPermaLink="false">Source code checked in, #57274 20100728101323P</guid></item><item><title>Updated Wiki: Blog</title><link>http://hl2glsl.codeplex.com/wikipage?title=Blog&amp;version=66</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Blog do Projeto&lt;/h1&gt;
Unfortunately this page exists only in portuguese. &lt;br /&gt;
&lt;h2&gt;06/01/10&lt;/h2&gt;Ol&amp;#225;,&lt;br /&gt;criei um projeto exclusivo para o OpenCL, e estarei postando l&amp;#225; as informa&amp;#231;&amp;#245;es relativas a essa etapa do projeto. Por favor, visitem &lt;a href="http://opencl.codeplex.com/" class="externalLink"&gt;http://opencl.codeplex.com/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; para maiores informa&amp;#231;&amp;#245;es.&lt;br /&gt;&lt;br /&gt;Att,&lt;br /&gt;&lt;br /&gt;Leonardo&lt;br /&gt;
&lt;h2&gt;12/11/09&lt;/h2&gt;Ol&amp;#225;,&lt;br /&gt;estou trabalhando no segundo tutorial sobre OpenCL, que acredito que deva estar pronto em breve. Nele pretendo discutir um pouco melhor OpenCL e a arquitetura sobre a qual ele deve executar. Pretendo nesse tutorial avan&amp;#231;ar mais tamb&amp;#233;m nas t&amp;#233;cnicas e possibilidades de programa&amp;#231;&amp;#227;o, abordando um pouco os diferentes tipos de mem&amp;#243;ria e sua rela&amp;#231;&amp;#227;o com a efici&amp;#234;ncia geral do programa.&lt;br /&gt;Estou tamb&amp;#233;m estudando uma forma de acelerar a execu&amp;#231;&amp;#227;o do trabalho de um doutorando aqui do grupo de computa&amp;#231;&amp;#227;o gr&amp;#225;fica. Ainda estou em uma fase bastante preliminar, mas em breve deverei estar publicando aqui mais informa&amp;#231;&amp;#245;es relacionadas a isso.&lt;br /&gt;&lt;br /&gt;At&amp;#233;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;03/11/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estive bastante envolvido com as tarefas da faculdade nos &amp;#250;ltimos dias, assim que n&amp;#227;o tenho tido muito tempo de postar aqui os resultados do meu trabalho.&lt;br /&gt;Encontrei um material muito bom sobre OpenCl aqui: &lt;a href="http://www.macresearch.org/opencl" class="externalLink"&gt;http://www.macresearch.org/opencl&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. Nelas s&amp;#227;o apresentados desde quest&amp;#245;es gerais sobre opencl at&amp;#233; otimiza&amp;#231;&amp;#245;es diversas. Vale a pena conferir.&lt;br /&gt;&lt;br /&gt;At&amp;#233;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;05/10/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;gostaria de fazer aqui um pequeno post apenas para comentar sobre um benchmark que foi feito pela SiSoftware (os respons&amp;#225;veis pelo famoso Sandra).&lt;br /&gt;O benchmark levou em considera&amp;#231;&amp;#227;o as vers&amp;#245;es 2.2 e 2.3 do driver da NVidia, comparando CUDA e Opencl. Os resultados completos podem ser conferidos aqui: &lt;a href="http://sisoftware.co.uk/index.html?dir=qa&amp;amp;location=gpu_opencl&amp;amp;langx=en&amp;amp;a=" class="externalLink"&gt;http://sisoftware.co.uk/index.html?dir=qa&amp;amp;location=gpu_opencl&amp;amp;langx=en&amp;amp;a=&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;A id&amp;#233;ia central &amp;#233; que o OpenCl est&amp;#225; praticamente &amp;#224; altura do CUDA (tendo em vista os testes desse benchmark) em termos de desempenho, o que responde a uma grande cr&amp;#237;tica ao OpenCL.&lt;br /&gt;&lt;br /&gt;Att,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;02/10/09&lt;/h2&gt;Bom dia,&lt;br /&gt;estou postando aqui hoje meu primeiro tutorial sobre OpenCL. Esse primeiro tutorial pretende ser uma inicia&amp;#231;&amp;#227;o, um hello world detalhado de como funciona uma aplica&amp;#231;&amp;#227;o OpenCl.&lt;br /&gt;Futuros tutoriais aprofundar-se-&amp;#227;o em outros temas;&lt;br /&gt;O tutorial pode ser encontrado aqui: &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=OpenCl%20Tutorials%20-%201&amp;referringTitle=Blog"&gt;OpenCl Tutorials - 1&lt;/a&gt;;&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;30/09/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;queria avisar que a nvidia liberou para a comunidade em geral o driver da vers&amp;#227;o 1.0 do OpenCL nesta segunda feira.&lt;br /&gt;A p&amp;#225;gina com informa&amp;#231;&amp;#245;es para download tanto de windows, linux e mac pode ser encontrada aqui: &lt;a href="http://www.nvidia.com/object/cuda_opencl.html" class="externalLink"&gt;http://www.nvidia.com/object/cuda_opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/09/09&lt;/h2&gt;Bom dia,&lt;br /&gt;Nessa &amp;#250;ltima semana fiz uma pequena apresenta&amp;#231;&amp;#227;o sobre o projeto, apresentando todas as suas fases. Disponibilizo aqui apresenta&amp;#231;&amp;#227;o com &amp;#225;udio &lt;a href="http://www.inf.ufrgs.br/~lpchatain/apresentacao_chatain.pptx" class="externalLink"&gt;http://www.inf.ufrgs.br/~lpchatain/apresentacao_chatain.pptx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;(~14mb) (o Microsoft Office 2007 &amp;#233; necess&amp;#225;rio para abrir a apresenta&amp;#231;&amp;#227;o, um plugin de compatibilidade para vers&amp;#245;es anteriores do Office pode ser encontrada aqui: &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=941b3470-3ae9-4aee-8f43-c6bb74cd1466&amp;amp;displaylang=en" class="externalLink"&gt;http://www.microsoft.com/downloads/details.aspx?familyid=941b3470-3ae9-4aee-8f43-c6bb74cd1466&amp;amp;displaylang=en&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;);&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;14/09/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;nesta &amp;#250;ltima semana estive tentando fazer um benchmark do Cuda. Trata-se de um programa que resolve o problema das n-rainhas*, desenvolvido em Cuda e C&lt;u&gt;&lt;/u&gt;. O trabalho em quest&amp;#227;o foi feito pelo Vitor, e pode ser conferido em &lt;a href="http://vitorpamplona.com/wiki/An%C3%A1lise%20de%20Performance:%20C%20vs%20Cuda" class="externalLink"&gt;http://vitorpamplona.com/wiki/An%C3%A1lise%20de%20Performance:%20C%20vs%20Cuda&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;Nesse trabalho foi concluido que a implementa&amp;#231;&amp;#227;o em C&lt;u&gt;&lt;/u&gt; estava mais eficiente que a em Cuda. Entretanto fora utilizada a vers&amp;#227;o 1.0 do Cuda, e minha inten&amp;#231;&amp;#227;o era fazer um novo teste com a nova vers&amp;#227;o do compilador, para verificar eventuais melhorias de performance. Tamb&amp;#233;m gostaria de fazer os testes com diferentes configura&amp;#231;&amp;#245;es de hardware.&lt;br /&gt;Entretanto estive com bastantes dificuldades em fazer os testes funcionarem. Eles apresentaram um comportamento an&amp;#244;malo (leia-se imprevis&amp;#237;vel) na m&amp;#225;quina em que iniciei os testes, e atribui o problema &amp;#224; arquitetura 64bits da nova m&amp;#225;quina. Mudando para um processador 32 bits n&amp;#227;o tenho problemas com a compila&amp;#231;&amp;#227;o, entretanto estou tendo problemas com os kernels, que falham em sua execu&amp;#231;ao. Acredito ser um pequeno problema com a mudan&amp;#231;a do compilador (1.0 -&amp;gt; 2.2), mas ainda n&amp;#227;o consegui identific&amp;#225;-lo.&lt;br /&gt;Estarei postando aqui em breve um relat&amp;#243;rio de meus testes.&lt;br /&gt;&lt;br /&gt;Fora isso continuo estudando OpenCl, o que &amp;#233; bastante parecido com Cuda, assim que vou &amp;#39;com as duas ao mesmo tempo&amp;#39;.&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;28/08/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estive estudando uma maneira de gerenciar automaticamente a inclus&amp;#227;o da DLL (como citado no post anterior). Postei algumas perguntas no blog da MSDN e obtive algumas respostas interessantes, que devem ser testadas nos proximos dias.&lt;br /&gt;&lt;br /&gt;Estive tamb&amp;#233;m estudando nessas &amp;#250;ltimas semanas &lt;b&gt;OpenCl&lt;/b&gt;.&lt;br /&gt;OpenCl &amp;#233; uma linguagem inicialmente criada pela Apple - e que teve como colaboradores a Intel, a nVidia e a AMD - para escrever programas que executem em ambientes heterogeneos, compostos de GPUs e CPUs.&lt;br /&gt;A linguagem foi &amp;#39;abra&amp;#231;ada&amp;#39; pelo Kronos Group, que disponibilizou recentemente a especifica&amp;#231;&amp;#227;o da vers&amp;#227;o 1.0.&lt;br /&gt;Atualmente existem apenas vers&amp;#245;es beta dos drivers (visto que o kronos group somente disponibiliza a especifica&amp;#231;&amp;#227;o, cabe &amp;#224;s fabricantes de hardware gr&amp;#225;fico implementarem essa especifica&amp;#231;&amp;#227;o e fornecerem um compilador e um driver/sdk.&lt;br /&gt;&lt;br /&gt;Eu estou aqui testando com o driver beta da nvidia (apenas para desenvolvedores registrados). A implementa&amp;#231;&amp;#227;o da nVidia nada mais &amp;#233; que um &amp;#39;mapeamento&amp;#39; da arquitetura CUDA para o OpenCl (creio que isso seja pr&amp;#243;ximo ao que a AMD/ATI est&amp;#225; fazendo, mapeando n&amp;#227;o para o CUDA mas para o Stream).&lt;br /&gt;&lt;br /&gt;Em CUDA, as fun&amp;#231;&amp;#245;es que se utilizam do paralelismo da GPU s&amp;#227;o conhecidas como &lt;i&gt;kernels&lt;/i&gt;.&lt;br /&gt;Kernels s&amp;#227;o executados por Streaming Multiprocessors (SMs). Cada SM, por sua vez, &amp;#233; composto por 8 Scalar Processors (SPs), os quais podem, cada um, executar simultaneamente at&amp;#233; 4 threads. Assim temos que um Streaming Multiprocessor pode executar simultaneamente at&amp;#233; 32 threads, o que chamaremos de &lt;i&gt;warp&lt;/i&gt;.&lt;br /&gt;Sempre que invocamos um kernel, especificamos para ele quantos &lt;i&gt;thread&lt;/i&gt; &lt;i&gt;blocks&lt;/i&gt; e quantas &lt;i&gt;threads&lt;/i&gt; &lt;i&gt;per&lt;/i&gt; &lt;i&gt;block&lt;/i&gt; queremos que esse kernel utilize. Cada SM encarrega-se da execu&amp;#231;&amp;#227;o de 1 thread block.&lt;br /&gt;Teoricamente, assim, se tivermos menos que 32 threads em um thread block estaremos &amp;#39;perdendo processamento&amp;#39;, pois n&amp;#227;o teremos preenchido o warp do SM. Se tivermos mais que 32 threads per block, entretanto, nossa situa&amp;#231;&amp;#227;o depender&amp;#225; da quantidade de mem&amp;#243;ria e de registradores que estar&amp;#227;o sendo utilizados. Funciona da seguinte forma: a CPU utiliza cache para esconder a latencia de mem&amp;#243;ria, i.e. para n&amp;#227;o termos que esperar sempre que os dados cheguem, n&amp;#243;s armazenamos-nos em uma cache. Na GPU escondemos a lat&amp;#234;ncia da mem&amp;#243;ria com computa&amp;#231;&amp;#245;es. Temos que a troca de contexto entre threads &amp;#233; muito veloz, assim ao inv&amp;#233;s de armazenarmos a mem&amp;#243;ria em uma grande cache, simplesmente mandamos outra thread executar enquanto esperamos, contanto que haja registradores livres no banco de registradores do SM.&lt;br /&gt;&lt;br /&gt;Em OpenCl temos a no&amp;#231;&amp;#227;o de &lt;i&gt;work-item&lt;/i&gt;s, que s&amp;#227;o mapeados para CUDA Threads, temos a no&amp;#231;&amp;#227;o de &lt;i&gt;work-groups&lt;/i&gt;, que s&amp;#227;o mapeados para thread blocks e por fim temos um NDRange, que &amp;#233; mapeado para um grid de thread blocks.&lt;br /&gt;O mapeamento &amp;#233; feito compilando OpenCl para o mesmo &amp;quot;bytecode&amp;quot;: PTX.&lt;br /&gt;&lt;br /&gt;Em breve estarei postando aqui trechos iniciais de c&amp;#243;digo em OpenCl, e espero estar fazendo alguns benchmarks com CUDA/OpenCl/CPU.&lt;br /&gt;&lt;br /&gt;Para maiores informa&amp;#231;&amp;#245;es a respeito das duas linguagens:
&lt;ul&gt;&lt;li&gt;Cuda:
&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.nvidia.com/object/cuda_home.html#" class="externalLink"&gt;http://www.nvidia.com/object/cuda_home.html#&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/CUDA" class="externalLink"&gt;http://en.wikipedia.org/wiki/CUDA&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ddj.com/hpc-high-performance-computing/207200659" class="externalLink"&gt;http://www.ddj.com/hpc-high-performance-computing/207200659&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;OpenCl
&lt;ul&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/OpenCL" class="externalLink"&gt;http://en.wikipedia.org/wiki/OpenCL&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.khronos.org/opencl/" class="externalLink"&gt;http://www.khronos.org/opencl/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.nvidia.com/object/cuda_opencl.html" class="externalLink"&gt;http://www.nvidia.com/object/cuda_opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ati.amd.com/technology/streamcomputing/opencl.html" class="externalLink"&gt;http://ati.amd.com/technology/streamcomputing/opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.openclworld.com/" class="externalLink"&gt;http://www.openclworld.com/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/07/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;Nesta semana estive com alguns problemas relativos &amp;#224; compatibilidade do debugger quando o projeto &amp;#233; levado a outros computadores. Esses problemas se deveram n&amp;#227;o &amp;#224; falta de compatibilidade do programa, mas sim do Package. Corrigi o problema, mas pretendo investigar a sua causa.&lt;br /&gt;Estou agora precisando ter acesso ao executavel gerado ap&amp;#243;s a compila&amp;#231;&amp;#227;o, estive dando uma olhada nisso nesta semana, sem muito sucesso. Al&amp;#233;m disso, preciso encontrar uma forma de manter sempre a DLL modificada como a acessivel pelo programa, ou seja, preciso de alguma forma manter a dll nas pastas do Visual Studio, no local onde o Package &amp;#233; instalado, e fazer com que tudo isso se ajeite na hora da instala&amp;#231;&amp;#227;o do pacote.&lt;br /&gt;Al&amp;#233;m desses pequenos problemas, continuo trabalhando na parte gr&amp;#225;fica (infelizmente n&amp;#227;o sou muito proficiente na cria&amp;#231;&amp;#227;o de interfaces amig&amp;#225;veis e bonitas) para integr&amp;#225;-la bem ao ambiente do Visual Studio. Ainda estou pensando em uma boa forma de dispor os compontentes, e em como melhorar a usabilidade do debugger.&lt;br /&gt;Fora isso ele se encontra bem integrado. &amp;#201; preciso fazer alguns testes, nos quais me dedicarei na pr&amp;#243;xima semana.&lt;br /&gt;&lt;br /&gt;At&amp;#233; la,&lt;br /&gt;&lt;br /&gt;Leonardo&lt;br /&gt;
&lt;h2&gt;08/07/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;Estou fazendo atualmente alguns ajustes automatizar mais o debugger, utilizando para isso as interface IVsRunningDocTableEvents, que implementa alguns m&amp;#233;todos para obter as notifica&amp;#231;&amp;#245;es sobre modifica&amp;#231;&amp;#245;es na IDE.&lt;br /&gt;Para poder passar a receber os eventos da IDE (que ser&amp;#227;o tratados pelos handlers da interface, a saber:
&lt;ul&gt;&lt;li&gt;int IVsRunningDocTableEvents.OnAfterAttributeChange&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterDocumentWindowHide&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterFirstDocumentLock&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterSave&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnBeforeDocumentWindowShow&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnBeforeLastDocumentUnlock&lt;/li&gt;&lt;/ul&gt;
)&lt;br /&gt;&lt;br /&gt;Esses eventos s&amp;#227;o importantes para que possamos ser notificados de modifica&amp;#231;&amp;#245;es importantes, como por exemplo saber quais s&amp;#227;o os documentos que est&amp;#227;o abertos.&lt;br /&gt;&lt;br /&gt;Para poder receber os eventos, devemos nos inscrever da seguinte forma:&lt;br /&gt;Declaramos inicialmente um cookie:
&lt;ul&gt;&lt;li&gt;uint cookie;&lt;/li&gt;&lt;/ul&gt;
E logo ap&amp;#243;s devemos declarar uma interface IVsRunningDocumentTable, e solicitar que ela avise sobre os eventos
&lt;ul&gt;&lt;li&gt;IVsRunningDocumentTable rdt = &lt;/li&gt;&lt;/ul&gt;
                (IVsRunningDocumentTable)Package.GetGlobalService(typeof(SVsRunningDocumentTable));
&lt;ul&gt;&lt;li&gt;rdt.AdviseRunningDocTableEvents(this, out dwCookie);&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Em breve, novas novidades.&lt;br /&gt;At&amp;#233;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;11/06/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;infelizemente, ap&amp;#243;s algum tempo de estudo em cima do debugger de exemplo, feito por Jackson Davis, dispon&amp;#237;vel em &lt;a href="http://code.msdn.microsoft.com/debugenginesample" class="externalLink"&gt;http://code.msdn.microsoft.com/debugenginesample&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;, e ap&amp;#243;s uma troca de e-mails com o mesmo, constatei que o desenvolvimento de uma debug engine para o VS, ou seja, o objetivo inicial de integrar totalmente o debugger de GLSL com o debugger do Visual Studio &amp;#233; demasiado complexa, visto que h&amp;#225; um grande n&amp;#250;mero de interfaces a implementar e que aparentemente o debugger de GLSL n&amp;#227;o &amp;#233; compat&amp;#237;vel com o modelo de debug engine que o Visual Studio espera. Com certeza ha uma maneira de realizar essa integra&amp;#231;ao, fazendo as devidas modifica&amp;#231;&amp;#245;es no debugger e implementando as interfaces requeridas pelo VS, mas esse trabalho levar&amp;#225; muito tempo.&lt;br /&gt;Portanto, dadas as condi&amp;#231;&amp;#245;es, optamos por desenvolver o depurador de forma externa ao depurador do Visual Studio, como j&amp;#225; vinha sendo feito em paralelo. Existe uma quantidade consideravel de melhorias que se podem fazer e &amp;#233; esse o atual objetivo.&lt;br /&gt;Tendo em vista o atual foco do trabalho, em pouco tempo espero estar postando alguns print screens e releases do debugger &amp;#39;integrado&amp;#39;.&lt;br /&gt;&lt;br /&gt;Obrigado,&lt;br /&gt;&lt;br /&gt;Leonardo&lt;br /&gt;
&lt;h2&gt;26/05/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estou utilizando os objetos DTE e DTE2 para alguns testes. Ainda tive alguns problemas ap&amp;#243;s o &amp;#250;ltimo post para conseguir o objeto, mas agora essa j&amp;#225; &amp;#233; uma quest&amp;#227;o do passado.&lt;br /&gt;Estive nessas semanas estudando os objetos DTE e DTE2 e tamb&amp;#233;m estudando um projeto de exemplo de um depurador C&lt;u&gt;&lt;/u&gt; integrado ao Visual Studio. Os resultados desse estudo ainda n&amp;#227;o s&amp;#227;o vis&amp;#237;veis no depurador GLSL.&lt;br /&gt;Quanto a altera&amp;#231;oes no depurador, coloquei uma lista com os shaders sendo editados no projeto, de forma que o usu&amp;#225;rio possa escolher mais facilmente qual o shader a ser escolhido. Vou seguir com algumas altera&amp;#231;&amp;#245;es visuais desse estilo para deixar o debugger mais amig&amp;#225;vel.&lt;br /&gt;&lt;br /&gt;At&amp;#233;&lt;br /&gt;
&lt;h2&gt;12/05/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;ontem descobri uma solu&amp;#231;&amp;#227;o interessante para um pequeno problema que me atormentou por bastante tempo e que pelo visto atormenta bastante gente ainda.&lt;br /&gt;Para solucionar uma s&amp;#233;rie de quest&amp;#245;es ao desenvolver VSPackages, podemos utilizar o &amp;quot;automation object&amp;quot; DTE, que representa o objeto de mais alta hierarquia no ambiente EnvDTE, que possui referencias a todos os elementos da automa&amp;#231;&amp;#227;o do n&amp;#250;cleo do VS. Para tanto declaramos uma interface DTE, pertencente ao namespace EnvDTE (&amp;#233; necess&amp;#225;rio adicionar uma Reference ao projeto: EnvDTE), e utilizamos o m&amp;#233;todo GetService para recuperar o objeto DTE (ele ser&amp;#225; referenciado pela interface DTE que declaramos).&lt;br /&gt;Pretendo colocar mais explica&amp;#231;&amp;#245;es sobre o objeto DTE nos proximos post, mas agora quero me concentrar na explica&amp;#231;&amp;#227;o e solu&amp;#231;&amp;#227;o do problema que me atormentou.&lt;br /&gt;Eis que o seguinte c&amp;#243;digo &amp;#233; o respons&amp;#225;vel por declarar e recuperar o objeto DTE:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; EnvDTE;

DTE dte;

&lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Initialize() {
&lt;span style="color:Green;"&gt;//Inicializa&amp;#231;&amp;#245;es&lt;/span&gt;

&lt;span style="color:Blue;"&gt;this&lt;/span&gt;.dte = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SDTE)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; DTE;
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Entretanto, ap&amp;#243;s a execu&amp;#231;&amp;#227;o do trecho, dte continuava sempre com valor null, o que acabava gerando exce&amp;#231;&amp;#245;es e obviamente n&amp;#227;o era o que deveria estar acontecendo.&lt;br /&gt;Buscando na internet, encontrei no VSX Team Blog (o blog do pessoal do VSX (Visual Studio Extensibility)) a solu&amp;#231;&amp;#227;o para meu problema.&lt;br /&gt;O fato &amp;#233; que caso o ambiente n&amp;#227;o esteja totalmente carregado (em &amp;quot;zombie state&amp;quot;), a solicita&amp;#231;&amp;#227;o da referencia do objeto DTE retorna null. Como eu queria que o package fosse carregado juntamente com o VS (no startup), a inicializa&amp;#231;&amp;#227;o do package ocorria antes de o ambiente estar totalmente carregado, e dte continha sempre o valor null.&lt;br /&gt;Assim, a solu&amp;#231;&amp;#227;o proposta pelo pessoal do blog &amp;#233; a seguinte: utilizar a interface IVsShellPropertyEvents, implementando o handler OnShellPropertyChange, o qual faz o tracking do estado da IDE. A propriedade que diz se o VS est&amp;#225; zombie &amp;#233; a VSPROPID_Zombie.&lt;br /&gt;Segue abaixo a implementa&amp;#231;&amp;#227;o do blog do pessoal do VSX:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
      DTE dte;
      &lt;span style="color:Blue;"&gt;uint&lt;/span&gt; cookie;
      &lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Initialize()
      {
           &lt;span style="color:Blue;"&gt;base&lt;/span&gt;.Initialize();
           IVsShell shellService = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsShell)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; IVsShell;
           &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (shellService != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
                ErrorHandler.ThrowOnFailure(shellService.AdviseShellPropertyChanges(&lt;span style="color:Blue;"&gt;this&lt;/span&gt;,&lt;span style="color:Blue;"&gt;out&lt;/span&gt; cookie));
           ...
        }

        &lt;span style="color:Blue;"&gt;#region&lt;/span&gt; IVsShellPropertyEvents Members

        &lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;int&lt;/span&gt; OnShellPropertyChange(&lt;span style="color:Blue;"&gt;int&lt;/span&gt; propid, &lt;span style="color:Blue;"&gt;object&lt;/span&gt; &lt;span style="color:Blue;"&gt;var&lt;/span&gt;)
        {
            &lt;span style="color:Green;"&gt;// when zombie state changes to false, finish package initialization&lt;/span&gt;
            &lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((&lt;span style="color:Blue;"&gt;int&lt;/span&gt;)__VSSPROPID.VSSPROPID_Zombie == propid)
            {
                &lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((&lt;span style="color:Blue;"&gt;bool&lt;/span&gt;)&lt;span style="color:Blue;"&gt;var&lt;/span&gt; == &lt;span style="color:Blue;"&gt;false&lt;/span&gt;)
                {
                    &lt;span style="color:Green;"&gt;// zombie state dependent code&lt;/span&gt;
                    &lt;span style="color:Blue;"&gt;this&lt;/span&gt;.dte = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SDTE)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; DTE;
                    &lt;span style="color:Green;"&gt;// eventlistener no longer needed&lt;/span&gt;
                    IVsShell shellService = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsShell)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; IVsShell;
                    &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (shellService != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
                        ErrorHandler.ThrowOnFailure(shellService.UnadviseShellPropertyChanges(&lt;span style="color:Blue;"&gt;this&lt;/span&gt;.cookie));
                    &lt;span style="color:Blue;"&gt;this&lt;/span&gt;.cookie = 0;
                }
            }

            &lt;span style="color:Blue;"&gt;return&lt;/span&gt; VSConstants.S_OK;

        }

        &lt;span style="color:Blue;"&gt;#endregion&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Esse artigo pode ser encontrado em &lt;a href="http://blogs.msdn.com/vsxteam/archive/2008/06/09/dr-ex-why-does-getservice-typeof-envdte-dte-return-null.aspx" class="externalLink"&gt;http://blogs.msdn.com/vsxteam/archive/2008/06/09/dr-ex-why-does-getservice-typeof-envdte-dte-return-null.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Nos proximos posts estarei descrevendo mais a fundo a parte t&amp;#233;cnica do VS que estudei at&amp;#233; agora, e introduzirei alguns dos problemas futuros que pretendo estar resolvendo.&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;06/05/09&lt;/h2&gt;Ol&amp;#225;,&lt;br /&gt;nestas ultimas semanas estive um pouco sobrecarregado, e n&amp;#227;o tive muito tempo para escrever no blog. A primeira etapa da depura&amp;#231;&amp;#227;o j&amp;#225; esta concluida, entretanto restam alguns bugs relativos ao depurador que devem ser resolvidos antes de ser lan&amp;#231;ado um release do plug-in.&lt;br /&gt;Venho trabalhando na parte mais profunda da integra&amp;#231;&amp;#227;o.&lt;br /&gt;Al&amp;#233;m da mera quest&amp;#227;o de mapear as funcionalidades do depurador para a IDE (que n&amp;#227;o &amp;#233; trivial), restam alguns problemas que surgem do fato de que algumas features existentes no VS n&amp;#227;o se encontram atualmente no depurador (como por exemplo a utiliza&amp;#231;&amp;#227;o de breakpoints). Essas funcionalidades dever&amp;#227;o ser implementadas em breve.&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/04/09&lt;/h2&gt;Oi,&lt;br /&gt;nesta semana finalizei uma primeira integra&amp;#231;&amp;#227;o. Neste primeiro est&amp;#225;gio temos, como j&amp;#225; foi dito, o depurador da B&amp;#225;rbara executando sobre o Visual Studio.&lt;br /&gt;H&amp;#225; ainda uma s&amp;#233;rie de melhorias que devem ser feitas sobre esta integra&amp;#231;&amp;#227;o:
&lt;ul&gt;&lt;li&gt;Melhorias na estrutura&amp;#231;&amp;#227;o e organiza&amp;#231;&amp;#227;o do c&amp;#243;digo;&lt;/li&gt;
&lt;li&gt;Remo&amp;#231;&amp;#227;o de alguns bugs;&lt;/li&gt;
&lt;li&gt;Melhor organiza&amp;#231;&amp;#227;o visual;&lt;/li&gt;&lt;/ul&gt;
At&amp;#233; o fim desta semana planejo ter uma vers&amp;#227;o utilizavel do depurador, melhor organizada visualmente, com algumas funcionalidades a mais (no que toca &amp;#224; integra&amp;#231;&amp;#227;o, por exemplo que o depurador saiba qual o shader que deve ser depurado automaticamente, assim como o programa opengl.&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;20/04/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estou tendo alguns problemas na integra&amp;#231;&amp;#227;o, que derivam diretamente de d&amp;#250;vidas com rela&amp;#231;&amp;#227;o ao depurador desenvolvido pela Barbara.&lt;br /&gt;A id&amp;#233;ia desta primeira integra&amp;#231;&amp;#227;o &amp;#233; bastante simples, uma simples adi&amp;#231;&amp;#227;o do depurador da barbara sobre o VS. A id&amp;#233;ia &amp;#233; que ap&amp;#243;s essa etapa seja construido incrementalmente o depurador integrado. Nesse ponto temos algumas dificuldades, como por exemplo que o depurador n&amp;#227;o suporta a coloca&amp;#231;&amp;#227;o de breakpoints, mas executa sempre passo a passo, de forma que n&amp;#227;o se pode definir de forma mais flexivel o fluxo do programa.&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;10/04/09&lt;/h2&gt;Ol&amp;#225;,&lt;br /&gt;nesta semana estive trabalhando na efetiva integra&amp;#231;&amp;#227;o do Depurador GLSL para o VS2008. A id&amp;#233;ia inicial inserir apenas o depurador de forma externa ao depurador do Visual Studio, o que &amp;#233; uma tarefa mais simples e deve ser terminada at&amp;#233; o final da semana. Nos proximos posts estarei publicando screenshots e maiores explica&amp;#231;&amp;#245;es sobre essa integra&amp;#231;&amp;#227;o. Esse trabalho tem a vantagem de que o depurador estar&amp;#225; rapidamente pronto para ser utilizado, entretanto ele n&amp;#227;o estara integrado com o depurador do Visual Studio. Para acess&amp;#225;-lo haver&amp;#227;o menus e janelas exclusivas que se encarregar&amp;#227;o de realizar todo o processo.&lt;br /&gt;Ap&amp;#243;s terminar essa primeira etapa de integra&amp;#231;&amp;#227;o, pretendo construir uma Debug Engine que se comunique com a SDM e torne o processo de depura&amp;#231;&amp;#227;o transparente ao usu&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;01/04/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;nas semanas anteriores eu estive estudando o desenvolvimento de VSPackages gen&amp;#233;ricos, como uma forma de me familiarizar com eles. Nesta semana, e nas que vir&amp;#227;o, me voltei efetivamente para o VSDebugger e como extend&amp;#234;-lo.&lt;br /&gt;&lt;br /&gt;Basicamente o debugger do visual studio &amp;#233; composto de tr&amp;#234;s partes:
&lt;ul&gt;&lt;li&gt;Interface com o usu&amp;#225;rio (UI), que permite, por exemplo, que sejam colocados breakpoints, que o codigo seja executado instru&amp;#231;&amp;#227;o a instru&amp;#231;&amp;#227;o, etc.&lt;/li&gt;
&lt;li&gt;SDM (Session Debug Manager), que &amp;#233; basicamente quem gerencia as Debug Engines. Pode ser visto como um multiplexador de Debug Engines, al&amp;#233;m de fazer a comunica&amp;#231;&amp;#227;o com a UI. A SDM &amp;#233; implementada pelo VS e n&amp;#227;o ser&amp;#225; alterada.&lt;/li&gt;
&lt;li&gt;Debug Engine (DE), que &amp;#233; o elemento que efetivamente faz a depura&amp;#231;&amp;#227;o do programa, e se comunica com a SDM. &amp;#201; aqui que ser&amp;#225; introduzido o depurador de GLSL.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Assim, teremos que construir uma DE que incorpore o depurador desenvolvido pela B&amp;#225;rbara. Para construir uma DE, s&amp;#227;o necess&amp;#225;rios alguns passos:
&lt;ul&gt;&lt;li&gt;Primeiro devemos registrar nossa DE no Visual Studio, permitindo que ele a reconhe&amp;#231;a e utilize;&lt;/li&gt;
&lt;li&gt;Nossa DE deve, quando solicitado pela SDM, &amp;quot;conectar-se&amp;quot; ao programa a ser depurado. Isso ocorre quando o usu&amp;#225;rio escolhe depurar o programa. Ocorre ent&amp;#227;o uma troca de mensagens entre a SDM e as DEs;&lt;/li&gt;
&lt;li&gt;Agora que nossa DE est&amp;#225; &amp;quot;conectada&amp;quot; ao programa efetivamente podemos nos concentrar em depurar o programa. Esta etapa consiste em:
&lt;ul&gt;&lt;li&gt;Controlar o fluxo de execu&amp;#231;&amp;#227;o, respeitando breakpoints e execu&amp;#231;&amp;#227;o step-by-step;&lt;/li&gt;
&lt;li&gt;Comunicar-se com a SDM, fazendo com que tanto o VS quanto o usu&amp;#225;rio tenham um feedback da depura&amp;#231;&amp;#227;o;&lt;/li&gt;
&lt;li&gt;Al&amp;#233;m disso temos que permitir:
&lt;ul&gt;&lt;li&gt;A cria&amp;#231;&amp;#227;o/dele&amp;#231;&amp;#227;o de breakpoints;&lt;/li&gt;
&lt;li&gt;A inser&amp;#231;&amp;#227;o de watches;&lt;/li&gt;
&lt;li&gt;A visualiza&amp;#231;&amp;#227;o da pilha de chamadas;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;A seguir devemos nos desconectar do programa e solicitar &amp;#224; SDM para que o mesmo seja terminado;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Neste momento estou estudando um pouco mais o trabalho da B&amp;#225;rbara. Minhas d&amp;#250;vidas se concentram em como exatamente integrar todo o sistema de debugging do Visual Studio ao depurador que j&amp;#225; foi desenvolvido. Nos pr&amp;#243;ximos posts procurarei explicar um pouco melhor o funcionamento do mecanismo de depura&amp;#231;&amp;#227;o do VS, al&amp;#233;m de tentar aproximar um pouco mais os dois debuggers.&lt;br /&gt;&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;25/03/09 - Hello World&lt;/h2&gt;Nesta semana continuei a estudar o desenvolvimento de um Package para o VS2008. O estudo foi dirigido basicamente aos procedimentos de cria&amp;#231;&amp;#227;o e ao funcionamento dos recursos gerados pelo wizard.&lt;br /&gt;&lt;br /&gt;Para iniciar o desenvolvimento de um VSPackage, ap&amp;#243;s baixar o SDK do Visual Studio, &amp;#233; utilizar o wizard de cria&amp;#231;&amp;#227;o de package, que se encarrega de gerar o c&amp;#243;digo base, deixando para n&amp;#243;s apenas o desenvolvimento do Package.&lt;br /&gt;Assim, ap&amp;#243;s definir o nome de nosso Package, somos perguntados a respeito de algumas coisas sobre o ele: a linguagem em que o desenvolveremos, se queremos uma Tool Window, um Menu Tool, etc.&lt;br /&gt;Para construir o Hello World utilizei C# e criei tanto uma Tool Window quanto um Menu Tool.&lt;br /&gt;Os resultados foram os seguintes:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Window&lt;/b&gt; &lt;b&gt;Tool:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63149" alt="windowTool.bmp" title="windowTool.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63150" alt="windowTool2.bmp" title="windowTool2.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo Fonte&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; okButton_Click(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, System.EventArgs e)
        {
            MessageBox.Show(&lt;span style="color:#A31515;"&gt;&amp;quot;Seu nome &amp;#233; &amp;quot;&lt;/span&gt; + nameBox.Text.ToString(), &lt;span style="color:#A31515;"&gt;&amp;quot;Seu nome&amp;quot;&lt;/span&gt;, MessageBoxButtons.OK);
        }

        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; limparButton_Click(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, System.EventArgs e)
        {
            nameBox.Text = &lt;span style="color:#A31515;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;;
        }

&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Command Tool:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63151" alt="cmdTool.bmp" title="cmdTool.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo fonte do command:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; MenuItemCallback(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, EventArgs e)
        {
            &lt;span style="color:Green;"&gt;// Show a Message Box to prove we were here&lt;/span&gt;
            IVsUIShell uiShell = (IVsUIShell)GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsUIShell));
            Guid clsid = Guid.Empty;
            &lt;span style="color:Blue;"&gt;int&lt;/span&gt; result;
            Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(uiShell.ShowMessageBox(
                       0,
                       &lt;span style="color:Blue;"&gt;ref&lt;/span&gt; clsid,
                       &lt;span style="color:#A31515;"&gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;,
                       &lt;span style="color:Blue;"&gt;string&lt;/span&gt;.Format(CultureInfo.CurrentCulture, &lt;span style="color:#A31515;"&gt;&amp;quot;Hello World - Este &amp;#233; um menuTool&amp;quot;&lt;/span&gt;),
                       &lt;span style="color:Blue;"&gt;string&lt;/span&gt;.Empty,
                       0,
                       OLEMSGBUTTON.OLEMSGBUTTON_OK,
                       OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST,
                       OLEMSGICON.OLEMSGICON_INFO,
                       0,        &lt;span style="color:Green;"&gt;// false&lt;/span&gt;
                       &lt;span style="color:Blue;"&gt;out&lt;/span&gt; result));
        }
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Nos proximos posts estarei explicando com mais detalhes o funcionamento desses elementos. Atualmente estou buscando algo mais proximo do debugger, assim que possivelmente nos proximos posts n&amp;#227;o estarei mais lidando com exemplos gen&amp;#233;ricos, mas com algo mais focado no debugger em si.&lt;br /&gt;Uma &amp;#243;tima refer&amp;#234;ncia (em ingles) &amp;#233; &lt;a href="http://learnvsxnow.codeplex.com/" class="externalLink"&gt;http://learnvsxnow.codeplex.com/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;17/03/09&lt;/h2&gt;Oi pessoal,&lt;br /&gt;sou o Leonardo e este &amp;#233; meu primeiro post aqui.&lt;br /&gt;Atualmente, como a Barbara comentou, estou estudando o desenvolvimento de um &amp;quot;plug-in&amp;quot; para o Visual Studio, que permita a integra&amp;#231;&amp;#227;o do trabalho dela com o ambiente de desenvolvimento, facilitando assim o trabalho de depura&amp;#231;&amp;#227;o.&lt;br /&gt;A id&amp;#233;ia &amp;#233; tornar o depurador natural ao usu&amp;#225;rio do VS.&lt;br /&gt;&lt;br /&gt;O desenvolvimento se far&amp;#225; a partir de VSPackages, que s&amp;#227;o a ferramenta de extensibilidade mas completa que a Microsoft prov&amp;#234; para o Visual Studio.&lt;br /&gt;&lt;br /&gt;Mais informa&amp;#231;&amp;#245;es sobre Visual Studio Extensibility, al&amp;#233;m do download dos SDKs do VS2005 e VS208, podem ser encontradas aqui: &lt;a href="http://msdn.microsoft.com/en-us/vsx/default.aspx" class="externalLink"&gt;http://msdn.microsoft.com/en-us/vsx/default.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; (Visual Studio Extensibility Developer Center).&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;08/03/2009&lt;/h2&gt;Nesta semana trabalhei corrigindo problemas na interface e procurei deixar o c&amp;#243;digo do depurador menos &amp;quot;duro&amp;quot;. Como por exemplo, poder abrir os arquivos em qualquer ordem e n&amp;#227;o primeiro um tipo de shader e depois o outro.&lt;br /&gt;
&lt;h2&gt;24/02/2009&lt;/h2&gt;Em virtude da troca de bolsistas, optamos por focar no desenvolvimento do plugin para o Visual Studio. Desta forma, o Leonardo est&amp;#225; estudando o desenvolvimento de plugins, enquanto eu estou arrumando o c&amp;#243;digo para que esta integra&amp;#231;&amp;#227;o possa ser feita.&lt;br /&gt;
&lt;h2&gt;18/02/2009&lt;/h2&gt;Fui aprovada para o Mestrado em Ci&amp;#234;ncia da Computa&amp;#231;&amp;#227;o - UFRGS, desta forma, a partir de mar&amp;#231;o estarei afastada do projeto. Quem ir&amp;#225; dar continuidade ao projeto &amp;#233; o aluno no quinto semestre de gradua&amp;#231;&amp;#227;o do curso de &lt;br /&gt;Ci&amp;#234;ncia da Computa&amp;#231;&amp;#227;o - UFRGS, Leonardo Chatain. Seja bem vindo, Leonardo!&lt;br /&gt;
&lt;h2&gt;18/01/2009&lt;/h2&gt;Como disse no &amp;#250;ltimo post, comecei a trabalhar na integra&amp;#231;&amp;#227;o da ferramenta com outras. &lt;br /&gt;A ferramenta com a qual estou fazendo integra&amp;#231;&amp;#227;o &amp;#233; a Shader Designer. A principal dificuldade encontrada at&amp;#233; o momento est&amp;#225; sendo portar o projeto da Shader Designer do Microsoft Visual Studio 2003 para o 2008 (ambiente em que foi desenvolvido o depurador). Estou tendo que re-escrever praticamente todo o c&amp;#243;digo. Al&amp;#233;m de que, o Shader Designer utiliza uma s&amp;#233;rie de c&amp;#243;digos fontes e de bibliotecas de terceiros (vide abaixo) que tamb&amp;#233;m est&amp;#227;o sendo portados. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digos Fontes de terceiros&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;a) 3DLabs GLSL Open Source Compiler &lt;br /&gt;&lt;br /&gt;b) Algumas fun&amp;#231;&amp;#245;es da &amp;quot;Matrix and Quaternion fAQ&amp;quot; &lt;br /&gt;&lt;br /&gt;c) AVI exporter &lt;br /&gt;&lt;br /&gt;d) GLEW Extensions manager.&lt;br /&gt;&lt;br /&gt;e) MeshMender da Nvidia&lt;br /&gt;&lt;br /&gt;f) DEV-IL&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Bibliotecas de terceiros&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;a) Compona&amp;#39;s SyntaxBox. &lt;br /&gt;&lt;br /&gt;b) Flexporter&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;15/12/2008&lt;/h2&gt;Nestas &amp;#250;ltimas semanas escrevi e apresentei um trabalho acad&amp;#234;mico sobre o assunto. A apresenta&amp;#231;&amp;#227;o pode ser obtida &lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=51900';"&gt;aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Tamb&amp;#233;m foram acrescentadas novas funcionalidades:
&lt;ul&gt;&lt;li&gt;Permite ao usu&amp;#225;rio optar por depurar:
&lt;ul&gt;&lt;li&gt;Apenas o shader;&lt;/li&gt;
&lt;li&gt;Apenas o programa OpenGL hospedeiro;&lt;/li&gt;
&lt;li&gt;Ambos.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;ul&gt;&lt;li&gt;Permite visualizar o valor atualizado das vari&amp;#225;veis que j&amp;#225; foram depuradas&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Nas pr&amp;#243;ximas semanas, vou iniciar o estudo sobre desenvolvimento de plugins e come&amp;#231;ar a integra&amp;#231;&amp;#227;o da ferramenta.&lt;br /&gt;
&lt;h2&gt;30/11/2008&lt;/h2&gt;Como dito no post anterior, foram muitas as dificuldades encontradas na utiliza&amp;#231;&amp;#227;o de extens&amp;#245;es para captura de dados da placa gr&amp;#225;fica.&lt;br /&gt;Para que outras pessoas que necessitem utilizar estas extens&amp;#245;es n&amp;#227;o enfrentem o mesmo problema (principalmente pela falta de documenta&amp;#231;&amp;#227;o e de exemplos de uso), coloquei na p&amp;#225;gina &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Capturing%20Data%20From%20Graphics%20Hardware&amp;referringTitle=Blog"&gt;Capturing Data From Graphics Hardware&lt;/a&gt;, uma explica&amp;#231;&amp;#227;o das extens&amp;#245;es utilizadas com exemplos. &lt;br /&gt;&lt;br /&gt;O depurador foi aprimorado. Agora &amp;#233; poss&amp;#237;vel n&amp;#227;o apenas ver o resultado da vari&amp;#225;vel que est&amp;#225; sendo depurada, mas tamb&amp;#233;m das fun&amp;#231;&amp;#245;es pr&amp;#233;-definidas da OpenGL Al&amp;#233;m disto, foi escrito um trabalho acad&amp;#234;mico sobre o assunto, que ap&amp;#243;s sua apresenta&amp;#231;&amp;#227;o, tamb&amp;#233;m estar&amp;#225; dispon&amp;#237;vel aqui no CodePlex.&lt;br /&gt;&lt;br /&gt;Em breve tamb&amp;#233;m estarei disponibilizando um realease do depurador.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;30/10/2008 - Finishing the Debugger&lt;/h2&gt;Durante este m&amp;#234;s me foquei em terminar o depurador GLSL.&lt;br /&gt;Foram muitas as dificuldades encontradas, principalmente na utiliza&amp;#231;&amp;#227;o de extens&amp;#245;es para capturar a sa&amp;#237;da dos processadores de v&amp;#233;rtices e de fragmentos.&lt;br /&gt;Foram implementados 3 m&amp;#243;dulos:
&lt;ul&gt;&lt;li&gt;Wrapper OpenGL -&amp;gt; respons&amp;#225;vel por capturar as opera&amp;#231;&amp;#245;es OpenGL realizadas pelo programa OpenGL hospedeiro e inserir os c&amp;#243;digos necess&amp;#225;rios para depura&amp;#231;&amp;#227;o;&lt;/li&gt;
&lt;li&gt;Parser GLSL -&amp;gt; respons&amp;#225;vel por re-escrever o c&amp;#243;digo do shader GLSL de modo a inserir as vari&amp;#225;veis de depura&amp;#231;&amp;#227;o necess&amp;#225;rias&lt;/li&gt;
&lt;li&gt;Interfce Gr&amp;#225;fica -&amp;gt; respons&amp;#225;vel por interligar e utilizar os resultados obtidos nos demais m&amp;#243;dulos, al&amp;#233;m de, &amp;#233; claro, ser a interface com o usu&amp;#225;rio.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Este trabalho foi apresentado no &lt;a href="http://www.propesq.ufrgs.br/sic2008/index.htm" class="externalLink"&gt;XX Sal&amp;#227;o de IC - UFRGS&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. A apresenta&amp;#231;&amp;#227;o pode ser baixada &lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=47908';"&gt;aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Para as pr&amp;#243;ximas semanas pretendo continuar trabalhando no aprimoramento da ferramenta e escrever um documento mais detalhado sobre seu desenvolvimento.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;30/09/2008 - GLSL Debugger&lt;/h2&gt;
Passei algum tempo sem postar no blog. Durante este tempo estava trabalhando em uma nova etapa do projeto, o desenvolvimento de um plugin de depura&amp;#231;&amp;#227;o de GLSL para o Visual Studio. Maiores detalhes do andamento e da descri&amp;#231;&amp;#227;o desta etapa podem ser encontrados em &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=GLSL%20Debugger&amp;referringTitle=Blog"&gt;GLSL Debugger&lt;/a&gt;.&lt;br /&gt;
&lt;h2&gt;18/08/2008&lt;/h2&gt;GLSL n&amp;#227;o possui suporte &amp;#224; cast impl&amp;#237;cito (ex: vec4 color = 0.5;) assim, acrescentei o cast explicito (ex: vec4 color = vec4(0.5); )&lt;br /&gt;&lt;br /&gt;Continuei com os testes do programa. A principal dificuldade encontrada nos testes &amp;#233; a valida&amp;#231;&amp;#227;o. Por enquanto, o m&amp;#233;todo utilizado para os testes consiste em pegar um c&amp;#243;digo HLSL v&amp;#225;lido, converter e testar em um compilador GLSL se o c&amp;#243;digo gerado &amp;#233; v&amp;#225;lido ou n&amp;#227;o. Se n&amp;#227;o for, o programa &amp;#233; corrigido. Ou seja, por falta de uma BNF oficial da HLSL, nossos testes s&amp;#227;o baseados em exemplos. O que n&amp;#227;o &amp;#233; o ideal. A id&amp;#233;ia &amp;#233; que a pr&amp;#243;xima etapa de testes seja realizada comparando as imagens geradas. Ou seja, ser&amp;#227;o obtidas imagens executando o shader HLSL e estas ser&amp;#227;o comparadas com as imagens obtidas atrav&amp;#233;s da execu&amp;#231;&amp;#227;o do shader GLSL. A diferen&amp;#231;a entre estas imagens nos dir&amp;#225; o percentual de erro obtido na convers&amp;#227;o. &amp;#201; mais uma forma de validar o programa, por&amp;#233;m, o fato dos testes serem baseados em exemplos persiste. Para que este fator n&amp;#227;o seja t&amp;#227;o relevante, estamos utilizando uma gama variada de exemplos.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;04/08/2008&lt;/h2&gt;Como o programa estava dispon&amp;#237;vel apenas em vers&amp;#245;es de linha de comando, desenvolvi uma vers&amp;#227;o que apresenta uma interface gr&amp;#225;fica simplificada. Com esta interface, basta o usu&amp;#225;rio carregar o c&amp;#243;digo HLSL e clicar em converter. Os c&amp;#243;digos s&amp;#227;o exibidos lado &amp;#224; lado, facilitando a visualiza&amp;#231;&amp;#227;o pelo usu&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;Esta interface apresenta um limitante, que &amp;#233; o fato de ser compat&amp;#237;vel apenas com sistemas Windows. Por&amp;#233;m, em breve, pretendo desenvolver uma vers&amp;#227;o compat&amp;#237;vel com outros sistemas.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;24/07/2008&lt;/h2&gt;GLSL n&amp;#227;o apresenta suporte ao comando &amp;quot;Switch&amp;quot;. Desta forma, fiz uma fun&amp;#231;&amp;#227;o que substitui este comando por &amp;quot;If..else&amp;quot;.&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;        switch ( teste ) {
    			case 0: k++; return teste; 
    			case 1: return teste; 
    			case 2: t++; return teste; 
    			default: { 
    				teste++;
       			} 
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;      if (teste == 0) { k++; return teste; }
      else if (teste == 1) { return teste;}
      else if (teste == 2) { t++; return teste; }
      else { teste++;  }
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;GLSL n&amp;#227;o permite atribui&amp;#231;&amp;#245;es para elementos dos vetores, se estes vetores forem vari&amp;#225;veis to tipo &amp;quot;varying&amp;quot;. Ent&amp;#227;o, fiz uma fun&amp;#231;&amp;#227;o que cria uma vari&amp;#225;vel tempor&amp;#225;ria, efetua a atribui&amp;#231;&amp;#227;o e ent&amp;#227;o atribui o valor &amp;#224; vari&amp;#225;vel original.&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;  float4 MyShader( float2 Tex : TEXCOORD0 ) : COLOR0
{
    float4 Color;
    
    Color = float4(1.0,1.0,1.0,1.0);
    Color.a;
    Color.a = 0.1;
    Color.rgb = float3(0.5f);

    Tex.y = Tex.y + (sin(timeraslow)*0.01);
    Tex.x = Tex.x + (cos(timeraslow)*0.01);
    Color = tex2D( g_samSrcColor, Tex.xy);

    Color -= tex2D( g_samSrcColor, Tex.xy-0.001)*2.0f;
    Color += tex2D( g_samSrcColor, Tex.xy+0.001)*2.0f;
    Color.rgb = float3((Color.r+Color.g+Color.b)/3.0f);   	
   	
    return Color;
}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt; varying vec2 Tex;

void main( )
{
    vec4 Color;
    
    Color = vec4(1.0,1.0,1.0,1.0);
    Color.a;
    Color.a = 0.1;
    Color.rgb = vec3(0.5); //n&amp;#227;o necessita de vari&amp;#225;vel tempor&amp;#225;ria pois n&amp;#227;o &amp;#233; varying

    vec2 tempTex = Tex; //como Tex era varying foi criada uma vari&amp;#225;vel tempor&amp;#225;ria 

    tempTex.y = Tex.y + (sin(timeraslow)*0.01);
    Tex=tempTex;
    tempTex.x = Tex.x + (cos(timeraslow)*0.01);
    Tex=tempTex;
    Color = tex2D( g_samSrcColor, Tex.xy);

    Color -= tex2D( g_samSrcColor, Tex.xy-0.001)*2.0;
    Color += tex2D( g_samSrcColor, Tex.xy+0.001)*2.0;
    Color.rgb = vec3((Color.r+Color.g+Color.b)/3.0));   	
   	
    gl_FragColor = Color;
}
&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;09/07/2008&lt;/h2&gt;Acrescentei a convers&amp;#227;o das fun&amp;#231;&amp;#245;es intr&amp;#237;nsicas. Para as fun&amp;#231;&amp;#245;es intr&amp;#237;nsicas de HLSL que n&amp;#227;o s&amp;#227;o suportadas pela GLSL (vide &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Differences%20Between%20HLSL%20and%20GLSL&amp;referringTitle=Blog"&gt;Differences Between HLSL and GLSL&lt;/a&gt;), &amp;#233; emitida uma mensagem de aviso ao usu&amp;#225;rio.  GLSL tamb&amp;#233;m n&amp;#227;o suporta a letra &amp;#39;f&amp;#39; ap&amp;#243;s um n&amp;#250;mero do tipo float (ex: 1.0f), ent&amp;#227;o, inseri uma fun&amp;#231;&amp;#227;o que remove este &amp;#39;f&amp;#39; do n&amp;#250;mero. &lt;br /&gt;&lt;br /&gt;Iniciei tamb&amp;#233;m a fase de testes do programa. Para isto estou utilizando os shaders  &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Parsing%20Shaders&amp;referringTitle=Blog"&gt;Parsing Shaders&lt;/a&gt;. Ap&amp;#243;s converter, executo o arquivo gerado no software &lt;a href="http://www.opengl.org/sdk/tools/ShaderDesigner" class="externalLink"&gt;Shader Designer&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. Este software &amp;#233; um editor/compilador de GLSL. Assim, atrav&amp;#233;s de sua sa&amp;#237;da, posso verificar se o c&amp;#243;digo GLSL gerado &amp;#233; v&amp;#225;lido ou n&amp;#227;o e corrigir os problemas encontrados.&lt;br /&gt;&lt;br /&gt;A vers&amp;#227;o mais atual dos fontes do projeto encontra-se &lt;a href="http://www.codeplex.com/hl2glsl/SourceControl/ListDownloadableCommits.aspx" class="externalLink"&gt;dispon&amp;#237;vel&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;04/07/2008&lt;/h2&gt;Fiz algumas altera&amp;#231;&amp;#245;es na gram&amp;#225;tica e acrescentei novas fun&amp;#231;&amp;#245;es para tratar estas altera&amp;#231;&amp;#245;es.&lt;br /&gt;&lt;br /&gt;Altera&amp;#231;&amp;#245;es na gram&amp;#225;tica:&lt;br /&gt;*Reconhecimento do par&amp;#226;metro &amp;quot;: Register&amp;quot;;&lt;br /&gt;*Reconhecimento do par&amp;#226;metro &amp;quot;: Packoffset&amp;quot;;&lt;br /&gt;*Reconhecimento do operador un&amp;#225;rio &amp;quot;!&amp;quot;;&lt;br /&gt;*Reconhecimento do tipo &amp;quot;uint&amp;quot;.&lt;br /&gt;&lt;br /&gt;GLSL n&amp;#227;o apresenta suporte para acesso &amp;#224; registradores. Assim, os par&amp;#226;metros &amp;quot;register&amp;quot; e &amp;quot;packoffset&amp;quot; n&amp;#227;o podem ser utilizados. A medida adotada para solucionar este problema &amp;#233; avisar ao usu&amp;#225;rio deste fato e perguntar se ele deseja remover estes par&amp;#226;metros. Caso ele opte por n&amp;#227;o remover, um aviso de que o c&amp;#243;digo gerado ser&amp;#225; inconsistente &amp;#233; emitido.&lt;br /&gt;&lt;br /&gt;O caso do tipo &amp;quot;uint&amp;quot; &amp;#233; similar, pois tamb&amp;#233;m n&amp;#227;o &amp;#233; suportado pela GLSL. S&amp;#243; que ao inv&amp;#233;s de remover a vari&amp;#225;vel, a op&amp;#231;&amp;#227;o dada ao usu&amp;#225;rio &amp;#233; a de troc&amp;#225;-lo pelo tipo int. &lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;18/06/2008&lt;/h2&gt;Passei a utilizar o Source Code Client do CodePlex para disponibilizar o c&amp;#243;digo fonte.&lt;br /&gt;&lt;br /&gt;Acrescentei as fun&amp;#231;&amp;#245;es para tratar &amp;quot;return&amp;quot; e o tipo da fun&amp;#231;&amp;#227;o &amp;quot;main&amp;quot;.&lt;br /&gt;&lt;br /&gt;Em GLSL &amp;#233; necess&amp;#225;rio uma fun&amp;#231;&amp;#227;o void main() que &amp;#233; de onde iniciar&amp;#225; a execu&amp;#231;&amp;#227;o.  Em HLSL, isto n&amp;#227;o &amp;#233; necess&amp;#225;rio.&lt;br /&gt;Assim, &amp;#233; preciso substituir o nome da fun&amp;#231;&amp;#227;o em HLSL por &amp;quot;main&amp;quot; e o tipo da fun&amp;#231;&amp;#227;o por void. O tipo da fun&amp;#231;&amp;#227;o deve ser salvo pois ele ser&amp;#225; utilizado na sa&amp;#237;da da fun&amp;#231;&amp;#227;o.  &lt;br /&gt;&lt;br /&gt;Como a fun&amp;#231;&amp;#227;o em GLSL &amp;#233; do tipo void, ela n&amp;#227;o tem mais o &amp;quot;return&amp;quot;.  Sua sa&amp;#237;da vai ser determinada de acordo com o tipo e os par&amp;#226;metros sem&amp;#226;nticos da fun&amp;#231;&amp;#227;o original, &lt;br /&gt;&lt;br /&gt;Ex: &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;float4 pixelShader( float4 color):COLOR
{
          float4 teste =float4(0,1,0,0);
          float4 tes   = color + teste;

          return tes;
} &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;varying vec4 color;

void main() { 

	vec4 teste = vec4(0,1,0,0);
	vec4 tes   = color + teste;
	
	gl_FragColor = vec4(tes) ;  
} &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;02/06/2008&lt;/h2&gt;
Disponibilizei os fontes em desenvolvimento do projeto na sess&amp;#227;o Releases nas vers&amp;#245;es de projeto para Mono e Visual Studio.&lt;br /&gt;
&lt;h2&gt;30/05/2008&lt;/h2&gt;
Comecei a entender mais a fundo o projeto. Para isto, estudei HLSL e aprendi as principais diferen&amp;#231;as entre as duas linguagens.&lt;br /&gt;Portei o projeto para o Visual Studio 2008. E fiz uma an&amp;#225;lise do que j&amp;#225; foi feito e do que ainda faltava fazer.&lt;br /&gt;Acrescentei as &amp;quot;System-value semantics&amp;quot; &amp;#224; gramatica. Estas sem&amp;#226;nticas est&amp;#227;o dispon&amp;#237;veis apenas no &lt;a href="http://msdn.microsoft.com/en-us/library/bb509647(VS.85).aspx#System_Value" class="externalLink"&gt;Direct 3D 10&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;15/05/2008&lt;/h2&gt;O projeto &amp;#233; desenvolvido em C#. Como n&amp;#227;o conhecia a linguagem, aproveitei para aprender em um curso.&lt;br /&gt;&lt;br /&gt;Este curso faz parte do programa Students2Business, criado pela Microsoft e desenvolvido pelos Centros de Inova&amp;#231;&amp;#227;o e institui&amp;#231;&amp;#245;es de ensino parceiras. Resumidamente: o programa &amp;#233; gratu&amp;#237;to, o aluno pode escolher entre aulas de desenvolvimento ou de infra-estrutura de TI e &amp;#233; divido em 3 etapas. Ao final de cada etapa h&amp;#225; uma prova classificat&amp;#243;ria para a etapa seguinte. As etapas 2 e 3 possuem dura&amp;#231;&amp;#227;o de 40hs. Ao final da terceira etapa, os alunos que apresentarem os melhores projetos finais podem realizar gratuitamente provas de certifica&amp;#231;&amp;#227;o Microsoft e todos os alunos que concluirem as 3 etapas ter&amp;#227;o direito a participar do evento de formatura. Maiores informa&amp;#231;&amp;#245;es sobre o programa em &lt;a href="http://proform.msdnbrasil.tempsite.ws/public/Default.aspx" class="externalLink"&gt;http://proform.msdnbrasil.tempsite.ws/public/Default.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;30/04/2008&lt;/h2&gt;
Ol&amp;#225;!&lt;br /&gt;&lt;br /&gt;Me chamo B&amp;#225;rbara e entrei no projeto para substituir o Vitor, que se afastou para fazer doutorado. Como ele, vou utilizar este espa&amp;#231;o para periodicamente publicar os avan&amp;#231;os do projeto.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;21/03/2008&lt;/h2&gt;
Nesta semana terminei a separa&amp;#231;&amp;#227;o das fun&amp;#231;&amp;#245;es em arquivos diferentes e iniciei algumas convers&amp;#245;es de nomes de vari&amp;#225;veis de acordo com um contexto sem&amp;#226;ntico. &lt;br /&gt;&lt;br /&gt;Por exemplo, enquanto em HLSL temos: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void main(
        float4 position   : POSITION, 
        float3 normal      : NORMAL, 
	float2 uv : TEXCOORD0,
	float3 lightDir : TEXCOORD1,
	float3 eyeDir : TEXCOORD2,
	float3 spotDir : TEXCOORD3,
	float3 lightDir1 : TEXCOORD4,
	float3 spotDir1 : TEXCOORD5,
	float4 shadowUV1 : TEXCOORD6,
	float4 shadowUV2 : TEXCOORD7)
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Em GLSL teremos: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
varying vec3 tangentEyeDir;
varying vec3 tangentLightDir[2];
varying vec3 tangentSpotDir[2];
varying vec4 shadowUV[2]; 
void main() { ... }
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;uv, position e normal no HLSL seriam as vari&amp;#225;veis pr&amp;#233;-definidas gl_TexCoord[0], gl_Vertex e gl_Normal  no GLSL. &lt;br /&gt;
&lt;h2&gt;14/03/2008&lt;/h2&gt;
Nesta semana comecei a construir o separador de fun&amp;#231;&amp;#245;es. De um arquivo HLSL pode-se gerar v&amp;#225;rios GLSL. Para tal utilizo o grafo de depend&amp;#234;ncias das fun&amp;#231;&amp;#245;es declaradas no arquivo e em seus includes para separar as fun&amp;#231;&amp;#245;es corretamente, levando para o arquivo correto a formata&amp;#231;&amp;#227;o desejada e os coment&amp;#225;rios pertinentes a ela.  &lt;br /&gt;
&lt;h2&gt;07/03/2008&lt;/h2&gt;
Enquanto o HLSL permite v&amp;#225;rias entradas de execu&amp;#231;&amp;#227;o, ou seja, v&amp;#225;rias fun&amp;#231;&amp;#245;es main, o GLSL s&amp;#243; permite uma e exige o nome main. Desta forma, esta semana, trabalhei na cria&amp;#231;&amp;#227;o de um grafo de chamadas de fun&amp;#231;&amp;#245;es, para determinar quais fun&amp;#231;&amp;#245;es est&amp;#227;o sendo utilizadas para cada fun&amp;#231;&amp;#227;o de entrada no HLSL. Com esse grafo, poderei colocar cada fun&amp;#231;&amp;#227;o de entrada do HLSL em um arquivo diferente, levando tamb&amp;#233;m suas fun&amp;#231;&amp;#245;es dependentes. &lt;br /&gt;
&lt;h2&gt;29/02/2008&lt;/h2&gt;
Nesta semana trabalhei com a migra&amp;#231;&amp;#227;o da declara&amp;#231;&amp;#227;o de vari&amp;#225;veis uniform e varying, de uma fun&amp;#231;&amp;#227;o para o contexto do arquivo. &lt;br /&gt;&lt;br /&gt;Do HLSL:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void funcao(
    // parameters 
    float4 position,
    uniform float4 lightPosition, // object space 
    uniform float4x4 texViewProj2) {..}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para o GLSL &lt;br /&gt;&lt;pre&gt;
// parameters 
uniform float4 lightPosition; // object space 
uniform float4x4 texViewProj2;

void funcao(
     float4 position
) {..}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Migra&amp;#231;&amp;#227;o simples, mas trabalhosa quando se tem uma &amp;#225;rvore de Tokens sem ignorar espa&amp;#231;os, coment&amp;#225;rios, novas linhas e tabula&amp;#231;&amp;#245;es. Acabei tento muita dificuldade em identificar os coment&amp;#225;rios relevantes que deveriam ser movidos juntamente com o par&amp;#226;metro.&lt;br /&gt;
&lt;h2&gt;22/02/2008&lt;/h2&gt;
Ol&amp;#225; a todos. &lt;br /&gt;&lt;br /&gt;Neste espa&amp;#231;o vou publicar os avan&amp;#231;os do projeto semanalmente. &lt;br /&gt;&lt;br /&gt;Nesta &amp;#250;ltima semana testei a &lt;a href="http://OGRE" class="externalLink"&gt;http://www.ogre3d.org/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; como arquitetura para os testes do projeto. Ao converter shaders de HLSL para GLSL, &amp;#233; necess&amp;#225;rio tamb&amp;#233;m converter o c&amp;#243;digo fonte do programa que os usa, da API do DirectX para a da OpenGL. Esta parte n&amp;#227;o &amp;#233; coberta por este projeto, portanto &amp;#233; manual. &lt;br /&gt;&lt;br /&gt;A OGRE &amp;#233; uma engine que permite o uso de shaders HLSL, Cg e GLSL de maneira unificada, removendo os links diretos ao DirectX ou ao OpenGL. Usando-a, n&amp;#227;o perderemos tempo migrando o c&amp;#243;digo fonte dos testes, apenas com os testes dos shaders. &lt;br /&gt;&lt;br /&gt;Tamb&amp;#233;m desenvolvi uma parte do conversor: 
&lt;ol&gt;&lt;li&gt;A troca da fun&amp;#231;&amp;#227;o &amp;quot;mul&amp;quot; pelo &amp;quot;*&amp;quot;&lt;/li&gt;
&lt;li&gt;A invers&amp;#227;o de par&amp;#226;metros na fun&amp;#231;&amp;#227;o &amp;quot;cross&amp;quot;&lt;/li&gt;
&lt;li&gt;A remo&amp;#231;&amp;#227;o de par&amp;#226;metros na fun&amp;#231;&amp;#227;o &amp;quot;main&amp;quot;&lt;/li&gt;&lt;/ol&gt;
&lt;br /&gt;E estudei algumas propriedades da representa&amp;#231;&amp;#227;o de matrizes das duas linguagens. Apesar dos elementos descritos na p&amp;#225;gina &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Differences%20Between%20HLSL%20and%20GLSL&amp;referringTitle=Blog"&gt;Differences Between HLSL and GLSL&lt;/a&gt;, ainda tenho d&amp;#250;vidas sobre o modo de trabalho com as matrizes, especialmente se devo ou n&amp;#227;o transp&amp;#244;-las.  &lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Wed, 06 Jan 2010 18:05:23 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Blog 20100106060523P</guid></item><item><title>Updated Wiki: Home</title><link>http://hl2glsl.codeplex.com/wikipage?version=26</link><description>&lt;div class="wikidoc"&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=30975" alt="logo6.jpg" title="logo6.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;HL2GLSL is a sub project of &lt;a href="http://www.codeplex.com/NDOS" class="externalLink"&gt;NDOS Project&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Video presentation: http://br.youtube.com/watch?v=46Tf8M-h2Y8&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=19581" alt="br.png" title="br.png" /&gt; &lt;b&gt;Descri&amp;#231;&amp;#227;o do Projeto&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;HL2GLSL &amp;#233; um aplicativo para converter c&amp;#243;digo da linguagem &lt;a href="http://en.wikipedia.org/wiki/High_Level_Shader_Language" class="externalLink"&gt;High Level Shading Language&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; para a linguagem &lt;a href="http://en.wikipedia.org/wiki/GLSL" class="externalLink"&gt;OpenGL Shading Language&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;, auxiliando o porte de jogos e aplicativos gr&amp;#225;ficos constru&amp;#237;dos para executarem em ambientes Windows para ambientes Linux/MacOS. Ambas as linguagens s&amp;#227;o tamb&amp;#233;m utilizadas para processamento paralelo, pois executam diretamente nas placas gr&amp;#225;ficas. O projeto esta sendo constru&amp;#237;do utilizando a linguagem C#, a &lt;a href="http://www.monodevelop.com/Main_Page" class="externalLink"&gt;IDE MonoDevelop&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; e o framework para gera&amp;#231;&amp;#227;o de compiladores &lt;a href="http://grammatica.percederberg.net/" class="externalLink"&gt;Grammatica&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Para maiores informa&amp;#231;&amp;#245;es sobre Shaders, leia: &lt;a href="http://www.vvvv.org/tiki-index.php?page=User+Shaders" class="externalLink"&gt;http://www.vvvv.org/tiki-index.php?page=User+Shaders&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=19582" alt="usa.png" title="usa.png" /&gt;  &lt;b&gt;Project Description&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;HL2GLSL is a translator between &lt;a href="http://en.wikipedia.org/wiki/High_Level_Shader_Language" class="externalLink"&gt;High Level Shading Language&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/GLSL" class="externalLink"&gt;OpenGL Shading Language&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. Since the HLSL shaders runs only in Microsoft Windows OS, the project aims to help game developers port their games to the Linux and MacOS systems. Both languages are also used to parallel processing in general purpose applications. The project uses C#, the  &lt;a href="http://grammatica.percederberg.net/" class="externalLink"&gt;Grammatica&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; compiler compiler and the &lt;a href="http://www.monodevelop.com/Main_Page" class="externalLink"&gt;MonoDevelop IDE&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;For more information about Shaders, see: &lt;a href="http://www.vvvv.org/tiki-index.php?page=User+Shaders" class="externalLink"&gt;http://www.vvvv.org/tiki-index.php?page=User+Shaders&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;See Also: &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Blog&amp;referringTitle=Home"&gt;Blog&lt;/a&gt;, &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=HLSL%20BNF&amp;referringTitle=Home"&gt;HLSL BNF&lt;/a&gt;, &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Parsing%20Shaders&amp;referringTitle=Home"&gt;Parsing Shaders&lt;/a&gt;, &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Development%20Tips&amp;referringTitle=Home"&gt;Development Tips&lt;/a&gt;, &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Differences%20Between%20HLSL%20and%20GLSL&amp;referringTitle=Home"&gt;Differences Between HLSL and GLSL&lt;/a&gt;,&lt;a href="http://hl2glsl.codeplex.com/wikipage?title=GLSL%20Debugger&amp;referringTitle=Home"&gt;GLSL Debugger&lt;/a&gt;,&lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Work%20Plan&amp;referringTitle=Home"&gt;Work Plan&lt;/a&gt;,&lt;a href="http://hl2glsl.codeplex.com/wikipage?title=OpenCL%20Tutorials&amp;referringTitle=Home"&gt;OpenCL Tutorials&lt;/a&gt;&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Wed, 06 Jan 2010 17:22:20 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Home 20100106052220P</guid></item><item><title>Updated Wiki: Blog</title><link>http://hl2glsl.codeplex.com/wikipage?title=Blog&amp;version=65</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Blog do Projeto&lt;/h1&gt;
Unfortunately this page exists only in portuguese. &lt;br /&gt;
&lt;h2&gt;12/11/09&lt;/h2&gt;Ol&amp;#225;,&lt;br /&gt;estou trabalhando no segundo tutorial sobre OpenCL, que acredito que deva estar pronto em breve. Nele pretendo discutir um pouco melhor OpenCL e a arquitetura sobre a qual ele deve executar. Pretendo nesse tutorial avan&amp;#231;ar mais tamb&amp;#233;m nas t&amp;#233;cnicas e possibilidades de programa&amp;#231;&amp;#227;o, abordando um pouco os diferentes tipos de mem&amp;#243;ria e sua rela&amp;#231;&amp;#227;o com a efici&amp;#234;ncia geral do programa.&lt;br /&gt;Estou tamb&amp;#233;m estudando uma forma de acelerar a execu&amp;#231;&amp;#227;o do trabalho de um doutorando aqui do grupo de computa&amp;#231;&amp;#227;o gr&amp;#225;fica. Ainda estou em uma fase bastante preliminar, mas em breve deverei estar publicando aqui mais informa&amp;#231;&amp;#245;es relacionadas a isso.&lt;br /&gt;&lt;br /&gt;At&amp;#233;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;03/11/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estive bastante envolvido com as tarefas da faculdade nos &amp;#250;ltimos dias, assim que n&amp;#227;o tenho tido muito tempo de postar aqui os resultados do meu trabalho.&lt;br /&gt;Encontrei um material muito bom sobre OpenCl aqui: &lt;a href="http://www.macresearch.org/opencl" class="externalLink"&gt;http://www.macresearch.org/opencl&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. Nelas s&amp;#227;o apresentados desde quest&amp;#245;es gerais sobre opencl at&amp;#233; otimiza&amp;#231;&amp;#245;es diversas. Vale a pena conferir.&lt;br /&gt;&lt;br /&gt;At&amp;#233;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;05/10/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;gostaria de fazer aqui um pequeno post apenas para comentar sobre um benchmark que foi feito pela SiSoftware (os respons&amp;#225;veis pelo famoso Sandra).&lt;br /&gt;O benchmark levou em considera&amp;#231;&amp;#227;o as vers&amp;#245;es 2.2 e 2.3 do driver da NVidia, comparando CUDA e Opencl. Os resultados completos podem ser conferidos aqui: &lt;a href="http://sisoftware.co.uk/index.html?dir=qa&amp;amp;location=gpu_opencl&amp;amp;langx=en&amp;amp;a=" class="externalLink"&gt;http://sisoftware.co.uk/index.html?dir=qa&amp;amp;location=gpu_opencl&amp;amp;langx=en&amp;amp;a=&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;A id&amp;#233;ia central &amp;#233; que o OpenCl est&amp;#225; praticamente &amp;#224; altura do CUDA (tendo em vista os testes desse benchmark) em termos de desempenho, o que responde a uma grande cr&amp;#237;tica ao OpenCL.&lt;br /&gt;&lt;br /&gt;Att,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;02/10/09&lt;/h2&gt;Bom dia,&lt;br /&gt;estou postando aqui hoje meu primeiro tutorial sobre OpenCL. Esse primeiro tutorial pretende ser uma inicia&amp;#231;&amp;#227;o, um hello world detalhado de como funciona uma aplica&amp;#231;&amp;#227;o OpenCl.&lt;br /&gt;Futuros tutoriais aprofundar-se-&amp;#227;o em outros temas;&lt;br /&gt;O tutorial pode ser encontrado aqui: &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=OpenCl%20Tutorials%20-%201&amp;referringTitle=Blog"&gt;OpenCl Tutorials - 1&lt;/a&gt;;&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;30/09/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;queria avisar que a nvidia liberou para a comunidade em geral o driver da vers&amp;#227;o 1.0 do OpenCL nesta segunda feira.&lt;br /&gt;A p&amp;#225;gina com informa&amp;#231;&amp;#245;es para download tanto de windows, linux e mac pode ser encontrada aqui: &lt;a href="http://www.nvidia.com/object/cuda_opencl.html" class="externalLink"&gt;http://www.nvidia.com/object/cuda_opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/09/09&lt;/h2&gt;Bom dia,&lt;br /&gt;Nessa &amp;#250;ltima semana fiz uma pequena apresenta&amp;#231;&amp;#227;o sobre o projeto, apresentando todas as suas fases. Disponibilizo aqui apresenta&amp;#231;&amp;#227;o com &amp;#225;udio &lt;a href="http://www.inf.ufrgs.br/~lpchatain/apresentacao_chatain.pptx" class="externalLink"&gt;http://www.inf.ufrgs.br/~lpchatain/apresentacao_chatain.pptx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;(~14mb) (o Microsoft Office 2007 &amp;#233; necess&amp;#225;rio para abrir a apresenta&amp;#231;&amp;#227;o, um plugin de compatibilidade para vers&amp;#245;es anteriores do Office pode ser encontrada aqui: &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=941b3470-3ae9-4aee-8f43-c6bb74cd1466&amp;amp;displaylang=en" class="externalLink"&gt;http://www.microsoft.com/downloads/details.aspx?familyid=941b3470-3ae9-4aee-8f43-c6bb74cd1466&amp;amp;displaylang=en&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;);&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;14/09/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;nesta &amp;#250;ltima semana estive tentando fazer um benchmark do Cuda. Trata-se de um programa que resolve o problema das n-rainhas*, desenvolvido em Cuda e C&lt;u&gt;&lt;/u&gt;. O trabalho em quest&amp;#227;o foi feito pelo Vitor, e pode ser conferido em &lt;a href="http://vitorpamplona.com/wiki/An%C3%A1lise%20de%20Performance:%20C%20vs%20Cuda" class="externalLink"&gt;http://vitorpamplona.com/wiki/An%C3%A1lise%20de%20Performance:%20C%20vs%20Cuda&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;Nesse trabalho foi concluido que a implementa&amp;#231;&amp;#227;o em C&lt;u&gt;&lt;/u&gt; estava mais eficiente que a em Cuda. Entretanto fora utilizada a vers&amp;#227;o 1.0 do Cuda, e minha inten&amp;#231;&amp;#227;o era fazer um novo teste com a nova vers&amp;#227;o do compilador, para verificar eventuais melhorias de performance. Tamb&amp;#233;m gostaria de fazer os testes com diferentes configura&amp;#231;&amp;#245;es de hardware.&lt;br /&gt;Entretanto estive com bastantes dificuldades em fazer os testes funcionarem. Eles apresentaram um comportamento an&amp;#244;malo (leia-se imprevis&amp;#237;vel) na m&amp;#225;quina em que iniciei os testes, e atribui o problema &amp;#224; arquitetura 64bits da nova m&amp;#225;quina. Mudando para um processador 32 bits n&amp;#227;o tenho problemas com a compila&amp;#231;&amp;#227;o, entretanto estou tendo problemas com os kernels, que falham em sua execu&amp;#231;ao. Acredito ser um pequeno problema com a mudan&amp;#231;a do compilador (1.0 -&amp;gt; 2.2), mas ainda n&amp;#227;o consegui identific&amp;#225;-lo.&lt;br /&gt;Estarei postando aqui em breve um relat&amp;#243;rio de meus testes.&lt;br /&gt;&lt;br /&gt;Fora isso continuo estudando OpenCl, o que &amp;#233; bastante parecido com Cuda, assim que vou 'com as duas ao mesmo tempo'.&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;28/08/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estive estudando uma maneira de gerenciar automaticamente a inclus&amp;#227;o da DLL (como citado no post anterior). Postei algumas perguntas no blog da MSDN e obtive algumas respostas interessantes, que devem ser testadas nos proximos dias.&lt;br /&gt;&lt;br /&gt;Estive tamb&amp;#233;m estudando nessas &amp;#250;ltimas semanas &lt;b&gt;OpenCl&lt;/b&gt;.&lt;br /&gt;OpenCl &amp;#233; uma linguagem inicialmente criada pela Apple - e que teve como colaboradores a Intel, a nVidia e a AMD - para escrever programas que executem em ambientes heterogeneos, compostos de GPUs e CPUs.&lt;br /&gt;A linguagem foi 'abra&amp;#231;ada' pelo Kronos Group, que disponibilizou recentemente a especifica&amp;#231;&amp;#227;o da vers&amp;#227;o 1.0.&lt;br /&gt;Atualmente existem apenas vers&amp;#245;es beta dos drivers (visto que o kronos group somente disponibiliza a especifica&amp;#231;&amp;#227;o, cabe &amp;#224;s fabricantes de hardware gr&amp;#225;fico implementarem essa especifica&amp;#231;&amp;#227;o e fornecerem um compilador e um driver/sdk.&lt;br /&gt;&lt;br /&gt;Eu estou aqui testando com o driver beta da nvidia (apenas para desenvolvedores registrados). A implementa&amp;#231;&amp;#227;o da nVidia nada mais &amp;#233; que um 'mapeamento' da arquitetura CUDA para o OpenCl (creio que isso seja pr&amp;#243;ximo ao que a AMD/ATI est&amp;#225; fazendo, mapeando n&amp;#227;o para o CUDA mas para o Stream).&lt;br /&gt;&lt;br /&gt;Em CUDA, as fun&amp;#231;&amp;#245;es que se utilizam do paralelismo da GPU s&amp;#227;o conhecidas como &lt;i&gt;kernels&lt;/i&gt;.&lt;br /&gt;Kernels s&amp;#227;o executados por Streaming Multiprocessors (SMs). Cada SM, por sua vez, &amp;#233; composto por 8 Scalar Processors (SPs), os quais podem, cada um, executar simultaneamente at&amp;#233; 4 threads. Assim temos que um Streaming Multiprocessor pode executar simultaneamente at&amp;#233; 32 threads, o que chamaremos de &lt;i&gt;warp&lt;/i&gt;.&lt;br /&gt;Sempre que invocamos um kernel, especificamos para ele quantos &lt;i&gt;thread&lt;/i&gt; &lt;i&gt;blocks&lt;/i&gt; e quantas &lt;i&gt;threads&lt;/i&gt; &lt;i&gt;per&lt;/i&gt; &lt;i&gt;block&lt;/i&gt; queremos que esse kernel utilize. Cada SM encarrega-se da execu&amp;#231;&amp;#227;o de 1 thread block.&lt;br /&gt;Teoricamente, assim, se tivermos menos que 32 threads em um thread block estaremos 'perdendo processamento', pois n&amp;#227;o teremos preenchido o warp do SM. Se tivermos mais que 32 threads per block, entretanto, nossa situa&amp;#231;&amp;#227;o depender&amp;#225; da quantidade de mem&amp;#243;ria e de registradores que estar&amp;#227;o sendo utilizados. Funciona da seguinte forma: a CPU utiliza cache para esconder a latencia de mem&amp;#243;ria, i.e. para n&amp;#227;o termos que esperar sempre que os dados cheguem, n&amp;#243;s armazenamos-nos em uma cache. Na GPU escondemos a lat&amp;#234;ncia da mem&amp;#243;ria com computa&amp;#231;&amp;#245;es. Temos que a troca de contexto entre threads &amp;#233; muito veloz, assim ao inv&amp;#233;s de armazenarmos a mem&amp;#243;ria em uma grande cache, simplesmente mandamos outra thread executar enquanto esperamos, contanto que haja registradores livres no banco de registradores do SM.&lt;br /&gt;&lt;br /&gt;Em OpenCl temos a no&amp;#231;&amp;#227;o de &lt;i&gt;work-item&lt;/i&gt;s, que s&amp;#227;o mapeados para CUDA Threads, temos a no&amp;#231;&amp;#227;o de &lt;i&gt;work-groups&lt;/i&gt;, que s&amp;#227;o mapeados para thread blocks e por fim temos um NDRange, que &amp;#233; mapeado para um grid de thread blocks.&lt;br /&gt;O mapeamento &amp;#233; feito compilando OpenCl para o mesmo &amp;quot;bytecode&amp;quot;: PTX.&lt;br /&gt;&lt;br /&gt;Em breve estarei postando aqui trechos iniciais de c&amp;#243;digo em OpenCl, e espero estar fazendo alguns benchmarks com CUDA/OpenCl/CPU.&lt;br /&gt;&lt;br /&gt;Para maiores informa&amp;#231;&amp;#245;es a respeito das duas linguagens:
&lt;ul&gt;&lt;li&gt;Cuda:
&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.nvidia.com/object/cuda_home.html#" class="externalLink"&gt;http://www.nvidia.com/object/cuda_home.html#&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/CUDA" class="externalLink"&gt;http://en.wikipedia.org/wiki/CUDA&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ddj.com/hpc-high-performance-computing/207200659" class="externalLink"&gt;http://www.ddj.com/hpc-high-performance-computing/207200659&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;OpenCl
&lt;ul&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/OpenCL" class="externalLink"&gt;http://en.wikipedia.org/wiki/OpenCL&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.khronos.org/opencl/" class="externalLink"&gt;http://www.khronos.org/opencl/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.nvidia.com/object/cuda_opencl.html" class="externalLink"&gt;http://www.nvidia.com/object/cuda_opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ati.amd.com/technology/streamcomputing/opencl.html" class="externalLink"&gt;http://ati.amd.com/technology/streamcomputing/opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.openclworld.com/" class="externalLink"&gt;http://www.openclworld.com/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/07/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;Nesta semana estive com alguns problemas relativos &amp;#224; compatibilidade do debugger quando o projeto &amp;#233; levado a outros computadores. Esses problemas se deveram n&amp;#227;o &amp;#224; falta de compatibilidade do programa, mas sim do Package. Corrigi o problema, mas pretendo investigar a sua causa.&lt;br /&gt;Estou agora precisando ter acesso ao executavel gerado ap&amp;#243;s a compila&amp;#231;&amp;#227;o, estive dando uma olhada nisso nesta semana, sem muito sucesso. Al&amp;#233;m disso, preciso encontrar uma forma de manter sempre a DLL modificada como a acessivel pelo programa, ou seja, preciso de alguma forma manter a dll nas pastas do Visual Studio, no local onde o Package &amp;#233; instalado, e fazer com que tudo isso se ajeite na hora da instala&amp;#231;&amp;#227;o do pacote.&lt;br /&gt;Al&amp;#233;m desses pequenos problemas, continuo trabalhando na parte gr&amp;#225;fica (infelizmente n&amp;#227;o sou muito proficiente na cria&amp;#231;&amp;#227;o de interfaces amig&amp;#225;veis e bonitas) para integr&amp;#225;-la bem ao ambiente do Visual Studio. Ainda estou pensando em uma boa forma de dispor os compontentes, e em como melhorar a usabilidade do debugger.&lt;br /&gt;Fora isso ele se encontra bem integrado. &amp;#201; preciso fazer alguns testes, nos quais me dedicarei na pr&amp;#243;xima semana.&lt;br /&gt;&lt;br /&gt;At&amp;#233; la,&lt;br /&gt;&lt;br /&gt;Leonardo&lt;br /&gt;
&lt;h2&gt;08/07/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;Estou fazendo atualmente alguns ajustes automatizar mais o debugger, utilizando para isso as interface IVsRunningDocTableEvents, que implementa alguns m&amp;#233;todos para obter as notifica&amp;#231;&amp;#245;es sobre modifica&amp;#231;&amp;#245;es na IDE.&lt;br /&gt;Para poder passar a receber os eventos da IDE (que ser&amp;#227;o tratados pelos handlers da interface, a saber:
&lt;ul&gt;&lt;li&gt;int IVsRunningDocTableEvents.OnAfterAttributeChange&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterDocumentWindowHide&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterFirstDocumentLock&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterSave&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnBeforeDocumentWindowShow&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnBeforeLastDocumentUnlock&lt;/li&gt;&lt;/ul&gt;
)&lt;br /&gt;&lt;br /&gt;Esses eventos s&amp;#227;o importantes para que possamos ser notificados de modifica&amp;#231;&amp;#245;es importantes, como por exemplo saber quais s&amp;#227;o os documentos que est&amp;#227;o abertos.&lt;br /&gt;&lt;br /&gt;Para poder receber os eventos, devemos nos inscrever da seguinte forma:&lt;br /&gt;Declaramos inicialmente um cookie:
&lt;ul&gt;&lt;li&gt;uint cookie;&lt;/li&gt;&lt;/ul&gt;
E logo ap&amp;#243;s devemos declarar uma interface IVsRunningDocumentTable, e solicitar que ela avise sobre os eventos
&lt;ul&gt;&lt;li&gt;IVsRunningDocumentTable rdt = &lt;/li&gt;&lt;/ul&gt;
                (IVsRunningDocumentTable)Package.GetGlobalService(typeof(SVsRunningDocumentTable));
&lt;ul&gt;&lt;li&gt;rdt.AdviseRunningDocTableEvents(this, out dwCookie);&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Em breve, novas novidades.&lt;br /&gt;At&amp;#233;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;11/06/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;infelizemente, ap&amp;#243;s algum tempo de estudo em cima do debugger de exemplo, feito por Jackson Davis, dispon&amp;#237;vel em &lt;a href="http://code.msdn.microsoft.com/debugenginesample" class="externalLink"&gt;http://code.msdn.microsoft.com/debugenginesample&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;, e ap&amp;#243;s uma troca de e-mails com o mesmo, constatei que o desenvolvimento de uma debug engine para o VS, ou seja, o objetivo inicial de integrar totalmente o debugger de GLSL com o debugger do Visual Studio &amp;#233; demasiado complexa, visto que h&amp;#225; um grande n&amp;#250;mero de interfaces a implementar e que aparentemente o debugger de GLSL n&amp;#227;o &amp;#233; compat&amp;#237;vel com o modelo de debug engine que o Visual Studio espera. Com certeza ha uma maneira de realizar essa integra&amp;#231;ao, fazendo as devidas modifica&amp;#231;&amp;#245;es no debugger e implementando as interfaces requeridas pelo VS, mas esse trabalho levar&amp;#225; muito tempo.&lt;br /&gt;Portanto, dadas as condi&amp;#231;&amp;#245;es, optamos por desenvolver o depurador de forma externa ao depurador do Visual Studio, como j&amp;#225; vinha sendo feito em paralelo. Existe uma quantidade consideravel de melhorias que se podem fazer e &amp;#233; esse o atual objetivo.&lt;br /&gt;Tendo em vista o atual foco do trabalho, em pouco tempo espero estar postando alguns print screens e releases do debugger 'integrado'.&lt;br /&gt;&lt;br /&gt;Obrigado,&lt;br /&gt;&lt;br /&gt;Leonardo&lt;br /&gt;
&lt;h2&gt;26/05/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estou utilizando os objetos DTE e DTE2 para alguns testes. Ainda tive alguns problemas ap&amp;#243;s o &amp;#250;ltimo post para conseguir o objeto, mas agora essa j&amp;#225; &amp;#233; uma quest&amp;#227;o do passado.&lt;br /&gt;Estive nessas semanas estudando os objetos DTE e DTE2 e tamb&amp;#233;m estudando um projeto de exemplo de um depurador C&lt;u&gt;&lt;/u&gt; integrado ao Visual Studio. Os resultados desse estudo ainda n&amp;#227;o s&amp;#227;o vis&amp;#237;veis no depurador GLSL.&lt;br /&gt;Quanto a altera&amp;#231;oes no depurador, coloquei uma lista com os shaders sendo editados no projeto, de forma que o usu&amp;#225;rio possa escolher mais facilmente qual o shader a ser escolhido. Vou seguir com algumas altera&amp;#231;&amp;#245;es visuais desse estilo para deixar o debugger mais amig&amp;#225;vel.&lt;br /&gt;&lt;br /&gt;At&amp;#233;&lt;br /&gt;
&lt;h2&gt;12/05/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;ontem descobri uma solu&amp;#231;&amp;#227;o interessante para um pequeno problema que me atormentou por bastante tempo e que pelo visto atormenta bastante gente ainda.&lt;br /&gt;Para solucionar uma s&amp;#233;rie de quest&amp;#245;es ao desenvolver VSPackages, podemos utilizar o &amp;quot;automation object&amp;quot; DTE, que representa o objeto de mais alta hierarquia no ambiente EnvDTE, que possui referencias a todos os elementos da automa&amp;#231;&amp;#227;o do n&amp;#250;cleo do VS. Para tanto declaramos uma interface DTE, pertencente ao namespace EnvDTE (&amp;#233; necess&amp;#225;rio adicionar uma Reference ao projeto: EnvDTE), e utilizamos o m&amp;#233;todo GetService para recuperar o objeto DTE (ele ser&amp;#225; referenciado pela interface DTE que declaramos).&lt;br /&gt;Pretendo colocar mais explica&amp;#231;&amp;#245;es sobre o objeto DTE nos proximos post, mas agora quero me concentrar na explica&amp;#231;&amp;#227;o e solu&amp;#231;&amp;#227;o do problema que me atormentou.&lt;br /&gt;Eis que o seguinte c&amp;#243;digo &amp;#233; o respons&amp;#225;vel por declarar e recuperar o objeto DTE:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; EnvDTE;

DTE dte;

&lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Initialize() {
&lt;span style="color:Green;"&gt;//Inicializa&amp;#231;&amp;#245;es&lt;/span&gt;

&lt;span style="color:Blue;"&gt;this&lt;/span&gt;.dte = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SDTE)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; DTE;
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Entretanto, ap&amp;#243;s a execu&amp;#231;&amp;#227;o do trecho, dte continuava sempre com valor null, o que acabava gerando exce&amp;#231;&amp;#245;es e obviamente n&amp;#227;o era o que deveria estar acontecendo.&lt;br /&gt;Buscando na internet, encontrei no VSX Team Blog (o blog do pessoal do VSX (Visual Studio Extensibility)) a solu&amp;#231;&amp;#227;o para meu problema.&lt;br /&gt;O fato &amp;#233; que caso o ambiente n&amp;#227;o esteja totalmente carregado (em &amp;quot;zombie state&amp;quot;), a solicita&amp;#231;&amp;#227;o da referencia do objeto DTE retorna null. Como eu queria que o package fosse carregado juntamente com o VS (no startup), a inicializa&amp;#231;&amp;#227;o do package ocorria antes de o ambiente estar totalmente carregado, e dte continha sempre o valor null.&lt;br /&gt;Assim, a solu&amp;#231;&amp;#227;o proposta pelo pessoal do blog &amp;#233; a seguinte: utilizar a interface IVsShellPropertyEvents, implementando o handler OnShellPropertyChange, o qual faz o tracking do estado da IDE. A propriedade que diz se o VS est&amp;#225; zombie &amp;#233; a VSPROPID_Zombie.&lt;br /&gt;Segue abaixo a implementa&amp;#231;&amp;#227;o do blog do pessoal do VSX:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
      DTE dte;
      &lt;span style="color:Blue;"&gt;uint&lt;/span&gt; cookie;
      &lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Initialize()
      {
           &lt;span style="color:Blue;"&gt;base&lt;/span&gt;.Initialize();
           IVsShell shellService = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsShell)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; IVsShell;
           &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (shellService != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
                ErrorHandler.ThrowOnFailure(shellService.AdviseShellPropertyChanges(&lt;span style="color:Blue;"&gt;this&lt;/span&gt;,&lt;span style="color:Blue;"&gt;out&lt;/span&gt; cookie));
           ...
        }

        &lt;span style="color:Blue;"&gt;#region&lt;/span&gt; IVsShellPropertyEvents Members

        &lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;int&lt;/span&gt; OnShellPropertyChange(&lt;span style="color:Blue;"&gt;int&lt;/span&gt; propid, &lt;span style="color:Blue;"&gt;object&lt;/span&gt; &lt;span style="color:Blue;"&gt;var&lt;/span&gt;)
        {
            &lt;span style="color:Green;"&gt;// when zombie state changes to false, finish package initialization&lt;/span&gt;
            &lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((&lt;span style="color:Blue;"&gt;int&lt;/span&gt;)__VSSPROPID.VSSPROPID_Zombie == propid)
            {
                &lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((&lt;span style="color:Blue;"&gt;bool&lt;/span&gt;)&lt;span style="color:Blue;"&gt;var&lt;/span&gt; == &lt;span style="color:Blue;"&gt;false&lt;/span&gt;)
                {
                    &lt;span style="color:Green;"&gt;// zombie state dependent code&lt;/span&gt;
                    &lt;span style="color:Blue;"&gt;this&lt;/span&gt;.dte = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SDTE)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; DTE;
                    &lt;span style="color:Green;"&gt;// eventlistener no longer needed&lt;/span&gt;
                    IVsShell shellService = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsShell)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; IVsShell;
                    &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (shellService != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
                        ErrorHandler.ThrowOnFailure(shellService.UnadviseShellPropertyChanges(&lt;span style="color:Blue;"&gt;this&lt;/span&gt;.cookie));
                    &lt;span style="color:Blue;"&gt;this&lt;/span&gt;.cookie = 0;
                }
            }

            &lt;span style="color:Blue;"&gt;return&lt;/span&gt; VSConstants.S_OK;

        }

        &lt;span style="color:Blue;"&gt;#endregion&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Esse artigo pode ser encontrado em &lt;a href="http://blogs.msdn.com/vsxteam/archive/2008/06/09/dr-ex-why-does-getservice-typeof-envdte-dte-return-null.aspx" class="externalLink"&gt;http://blogs.msdn.com/vsxteam/archive/2008/06/09/dr-ex-why-does-getservice-typeof-envdte-dte-return-null.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Nos proximos posts estarei descrevendo mais a fundo a parte t&amp;#233;cnica do VS que estudei at&amp;#233; agora, e introduzirei alguns dos problemas futuros que pretendo estar resolvendo.&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;06/05/09&lt;/h2&gt;Ol&amp;#225;,&lt;br /&gt;nestas ultimas semanas estive um pouco sobrecarregado, e n&amp;#227;o tive muito tempo para escrever no blog. A primeira etapa da depura&amp;#231;&amp;#227;o j&amp;#225; esta concluida, entretanto restam alguns bugs relativos ao depurador que devem ser resolvidos antes de ser lan&amp;#231;ado um release do plug-in.&lt;br /&gt;Venho trabalhando na parte mais profunda da integra&amp;#231;&amp;#227;o.&lt;br /&gt;Al&amp;#233;m da mera quest&amp;#227;o de mapear as funcionalidades do depurador para a IDE (que n&amp;#227;o &amp;#233; trivial), restam alguns problemas que surgem do fato de que algumas features existentes no VS n&amp;#227;o se encontram atualmente no depurador (como por exemplo a utiliza&amp;#231;&amp;#227;o de breakpoints). Essas funcionalidades dever&amp;#227;o ser implementadas em breve.&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/04/09&lt;/h2&gt;Oi,&lt;br /&gt;nesta semana finalizei uma primeira integra&amp;#231;&amp;#227;o. Neste primeiro est&amp;#225;gio temos, como j&amp;#225; foi dito, o depurador da B&amp;#225;rbara executando sobre o Visual Studio.&lt;br /&gt;H&amp;#225; ainda uma s&amp;#233;rie de melhorias que devem ser feitas sobre esta integra&amp;#231;&amp;#227;o:
&lt;ul&gt;&lt;li&gt;Melhorias na estrutura&amp;#231;&amp;#227;o e organiza&amp;#231;&amp;#227;o do c&amp;#243;digo;&lt;/li&gt;
&lt;li&gt;Remo&amp;#231;&amp;#227;o de alguns bugs;&lt;/li&gt;
&lt;li&gt;Melhor organiza&amp;#231;&amp;#227;o visual;&lt;/li&gt;&lt;/ul&gt;
At&amp;#233; o fim desta semana planejo ter uma vers&amp;#227;o utilizavel do depurador, melhor organizada visualmente, com algumas funcionalidades a mais (no que toca &amp;#224; integra&amp;#231;&amp;#227;o, por exemplo que o depurador saiba qual o shader que deve ser depurado automaticamente, assim como o programa opengl.&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;20/04/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estou tendo alguns problemas na integra&amp;#231;&amp;#227;o, que derivam diretamente de d&amp;#250;vidas com rela&amp;#231;&amp;#227;o ao depurador desenvolvido pela Barbara.&lt;br /&gt;A id&amp;#233;ia desta primeira integra&amp;#231;&amp;#227;o &amp;#233; bastante simples, uma simples adi&amp;#231;&amp;#227;o do depurador da barbara sobre o VS. A id&amp;#233;ia &amp;#233; que ap&amp;#243;s essa etapa seja construido incrementalmente o depurador integrado. Nesse ponto temos algumas dificuldades, como por exemplo que o depurador n&amp;#227;o suporta a coloca&amp;#231;&amp;#227;o de breakpoints, mas executa sempre passo a passo, de forma que n&amp;#227;o se pode definir de forma mais flexivel o fluxo do programa.&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;10/04/09&lt;/h2&gt;Ol&amp;#225;,&lt;br /&gt;nesta semana estive trabalhando na efetiva integra&amp;#231;&amp;#227;o do Depurador GLSL para o VS2008. A id&amp;#233;ia inicial inserir apenas o depurador de forma externa ao depurador do Visual Studio, o que &amp;#233; uma tarefa mais simples e deve ser terminada at&amp;#233; o final da semana. Nos proximos posts estarei publicando screenshots e maiores explica&amp;#231;&amp;#245;es sobre essa integra&amp;#231;&amp;#227;o. Esse trabalho tem a vantagem de que o depurador estar&amp;#225; rapidamente pronto para ser utilizado, entretanto ele n&amp;#227;o estara integrado com o depurador do Visual Studio. Para acess&amp;#225;-lo haver&amp;#227;o menus e janelas exclusivas que se encarregar&amp;#227;o de realizar todo o processo.&lt;br /&gt;Ap&amp;#243;s terminar essa primeira etapa de integra&amp;#231;&amp;#227;o, pretendo construir uma Debug Engine que se comunique com a SDM e torne o processo de depura&amp;#231;&amp;#227;o transparente ao usu&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;01/04/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;nas semanas anteriores eu estive estudando o desenvolvimento de VSPackages gen&amp;#233;ricos, como uma forma de me familiarizar com eles. Nesta semana, e nas que vir&amp;#227;o, me voltei efetivamente para o VSDebugger e como extend&amp;#234;-lo.&lt;br /&gt;&lt;br /&gt;Basicamente o debugger do visual studio &amp;#233; composto de tr&amp;#234;s partes:
&lt;ul&gt;&lt;li&gt;Interface com o usu&amp;#225;rio (UI), que permite, por exemplo, que sejam colocados breakpoints, que o codigo seja executado instru&amp;#231;&amp;#227;o a instru&amp;#231;&amp;#227;o, etc.&lt;/li&gt;
&lt;li&gt;SDM (Session Debug Manager), que &amp;#233; basicamente quem gerencia as Debug Engines. Pode ser visto como um multiplexador de Debug Engines, al&amp;#233;m de fazer a comunica&amp;#231;&amp;#227;o com a UI. A SDM &amp;#233; implementada pelo VS e n&amp;#227;o ser&amp;#225; alterada.&lt;/li&gt;
&lt;li&gt;Debug Engine (DE), que &amp;#233; o elemento que efetivamente faz a depura&amp;#231;&amp;#227;o do programa, e se comunica com a SDM. &amp;#201; aqui que ser&amp;#225; introduzido o depurador de GLSL.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Assim, teremos que construir uma DE que incorpore o depurador desenvolvido pela B&amp;#225;rbara. Para construir uma DE, s&amp;#227;o necess&amp;#225;rios alguns passos:
&lt;ul&gt;&lt;li&gt;Primeiro devemos registrar nossa DE no Visual Studio, permitindo que ele a reconhe&amp;#231;a e utilize;&lt;/li&gt;
&lt;li&gt;Nossa DE deve, quando solicitado pela SDM, &amp;quot;conectar-se&amp;quot; ao programa a ser depurado. Isso ocorre quando o usu&amp;#225;rio escolhe depurar o programa. Ocorre ent&amp;#227;o uma troca de mensagens entre a SDM e as DEs;&lt;/li&gt;
&lt;li&gt;Agora que nossa DE est&amp;#225; &amp;quot;conectada&amp;quot; ao programa efetivamente podemos nos concentrar em depurar o programa. Esta etapa consiste em:
&lt;ul&gt;&lt;li&gt;Controlar o fluxo de execu&amp;#231;&amp;#227;o, respeitando breakpoints e execu&amp;#231;&amp;#227;o step-by-step;&lt;/li&gt;
&lt;li&gt;Comunicar-se com a SDM, fazendo com que tanto o VS quanto o usu&amp;#225;rio tenham um feedback da depura&amp;#231;&amp;#227;o;&lt;/li&gt;
&lt;li&gt;Al&amp;#233;m disso temos que permitir:
&lt;ul&gt;&lt;li&gt;A cria&amp;#231;&amp;#227;o/dele&amp;#231;&amp;#227;o de breakpoints;&lt;/li&gt;
&lt;li&gt;A inser&amp;#231;&amp;#227;o de watches;&lt;/li&gt;
&lt;li&gt;A visualiza&amp;#231;&amp;#227;o da pilha de chamadas;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;A seguir devemos nos desconectar do programa e solicitar &amp;#224; SDM para que o mesmo seja terminado;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Neste momento estou estudando um pouco mais o trabalho da B&amp;#225;rbara. Minhas d&amp;#250;vidas se concentram em como exatamente integrar todo o sistema de debugging do Visual Studio ao depurador que j&amp;#225; foi desenvolvido. Nos pr&amp;#243;ximos posts procurarei explicar um pouco melhor o funcionamento do mecanismo de depura&amp;#231;&amp;#227;o do VS, al&amp;#233;m de tentar aproximar um pouco mais os dois debuggers.&lt;br /&gt;&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;25/03/09 - Hello World&lt;/h2&gt;Nesta semana continuei a estudar o desenvolvimento de um Package para o VS2008. O estudo foi dirigido basicamente aos procedimentos de cria&amp;#231;&amp;#227;o e ao funcionamento dos recursos gerados pelo wizard.&lt;br /&gt;&lt;br /&gt;Para iniciar o desenvolvimento de um VSPackage, ap&amp;#243;s baixar o SDK do Visual Studio, &amp;#233; utilizar o wizard de cria&amp;#231;&amp;#227;o de package, que se encarrega de gerar o c&amp;#243;digo base, deixando para n&amp;#243;s apenas o desenvolvimento do Package.&lt;br /&gt;Assim, ap&amp;#243;s definir o nome de nosso Package, somos perguntados a respeito de algumas coisas sobre o ele: a linguagem em que o desenvolveremos, se queremos uma Tool Window, um Menu Tool, etc.&lt;br /&gt;Para construir o Hello World utilizei C# e criei tanto uma Tool Window quanto um Menu Tool.&lt;br /&gt;Os resultados foram os seguintes:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Window&lt;/b&gt; &lt;b&gt;Tool:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63149" alt="windowTool.bmp" title="windowTool.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63150" alt="windowTool2.bmp" title="windowTool2.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo Fonte&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; okButton_Click(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, System.EventArgs e)
        {
            MessageBox.Show(&lt;span style="color:#A31515;"&gt;&amp;quot;Seu nome &amp;#233; &amp;quot;&lt;/span&gt; + nameBox.Text.ToString(), &lt;span style="color:#A31515;"&gt;&amp;quot;Seu nome&amp;quot;&lt;/span&gt;, MessageBoxButtons.OK);
        }

        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; limparButton_Click(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, System.EventArgs e)
        {
            nameBox.Text = &lt;span style="color:#A31515;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;;
        }

&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Command Tool:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63151" alt="cmdTool.bmp" title="cmdTool.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo fonte do command:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; MenuItemCallback(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, EventArgs e)
        {
            &lt;span style="color:Green;"&gt;// Show a Message Box to prove we were here&lt;/span&gt;
            IVsUIShell uiShell = (IVsUIShell)GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsUIShell));
            Guid clsid = Guid.Empty;
            &lt;span style="color:Blue;"&gt;int&lt;/span&gt; result;
            Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(uiShell.ShowMessageBox(
                       0,
                       &lt;span style="color:Blue;"&gt;ref&lt;/span&gt; clsid,
                       &lt;span style="color:#A31515;"&gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;,
                       &lt;span style="color:Blue;"&gt;string&lt;/span&gt;.Format(CultureInfo.CurrentCulture, &lt;span style="color:#A31515;"&gt;&amp;quot;Hello World - Este &amp;#233; um menuTool&amp;quot;&lt;/span&gt;),
                       &lt;span style="color:Blue;"&gt;string&lt;/span&gt;.Empty,
                       0,
                       OLEMSGBUTTON.OLEMSGBUTTON_OK,
                       OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST,
                       OLEMSGICON.OLEMSGICON_INFO,
                       0,        &lt;span style="color:Green;"&gt;// false&lt;/span&gt;
                       &lt;span style="color:Blue;"&gt;out&lt;/span&gt; result));
        }
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Nos proximos posts estarei explicando com mais detalhes o funcionamento desses elementos. Atualmente estou buscando algo mais proximo do debugger, assim que possivelmente nos proximos posts n&amp;#227;o estarei mais lidando com exemplos gen&amp;#233;ricos, mas com algo mais focado no debugger em si.&lt;br /&gt;Uma &amp;#243;tima refer&amp;#234;ncia (em ingles) &amp;#233; &lt;a href="http://learnvsxnow.codeplex.com/" class="externalLink"&gt;http://learnvsxnow.codeplex.com/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;17/03/09&lt;/h2&gt;Oi pessoal,&lt;br /&gt;sou o Leonardo e este &amp;#233; meu primeiro post aqui.&lt;br /&gt;Atualmente, como a Barbara comentou, estou estudando o desenvolvimento de um &amp;quot;plug-in&amp;quot; para o Visual Studio, que permita a integra&amp;#231;&amp;#227;o do trabalho dela com o ambiente de desenvolvimento, facilitando assim o trabalho de depura&amp;#231;&amp;#227;o.&lt;br /&gt;A id&amp;#233;ia &amp;#233; tornar o depurador natural ao usu&amp;#225;rio do VS.&lt;br /&gt;&lt;br /&gt;O desenvolvimento se far&amp;#225; a partir de VSPackages, que s&amp;#227;o a ferramenta de extensibilidade mas completa que a Microsoft prov&amp;#234; para o Visual Studio.&lt;br /&gt;&lt;br /&gt;Mais informa&amp;#231;&amp;#245;es sobre Visual Studio Extensibility, al&amp;#233;m do download dos SDKs do VS2005 e VS208, podem ser encontradas aqui: &lt;a href="http://msdn.microsoft.com/en-us/vsx/default.aspx" class="externalLink"&gt;http://msdn.microsoft.com/en-us/vsx/default.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; (Visual Studio Extensibility Developer Center).&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;08/03/2009&lt;/h2&gt;Nesta semana trabalhei corrigindo problemas na interface e procurei deixar o c&amp;#243;digo do depurador menos &amp;quot;duro&amp;quot;. Como por exemplo, poder abrir os arquivos em qualquer ordem e n&amp;#227;o primeiro um tipo de shader e depois o outro.&lt;br /&gt;
&lt;h2&gt;24/02/2009&lt;/h2&gt;Em virtude da troca de bolsistas, optamos por focar no desenvolvimento do plugin para o Visual Studio. Desta forma, o Leonardo est&amp;#225; estudando o desenvolvimento de plugins, enquanto eu estou arrumando o c&amp;#243;digo para que esta integra&amp;#231;&amp;#227;o possa ser feita.&lt;br /&gt;
&lt;h2&gt;18/02/2009&lt;/h2&gt;Fui aprovada para o Mestrado em Ci&amp;#234;ncia da Computa&amp;#231;&amp;#227;o - UFRGS, desta forma, a partir de mar&amp;#231;o estarei afastada do projeto. Quem ir&amp;#225; dar continuidade ao projeto &amp;#233; o aluno no quinto semestre de gradua&amp;#231;&amp;#227;o do curso de &lt;br /&gt;Ci&amp;#234;ncia da Computa&amp;#231;&amp;#227;o - UFRGS, Leonardo Chatain. Seja bem vindo, Leonardo!&lt;br /&gt;
&lt;h2&gt;18/01/2009&lt;/h2&gt;Como disse no &amp;#250;ltimo post, comecei a trabalhar na integra&amp;#231;&amp;#227;o da ferramenta com outras. &lt;br /&gt;A ferramenta com a qual estou fazendo integra&amp;#231;&amp;#227;o &amp;#233; a Shader Designer. A principal dificuldade encontrada at&amp;#233; o momento est&amp;#225; sendo portar o projeto da Shader Designer do Microsoft Visual Studio 2003 para o 2008 (ambiente em que foi desenvolvido o depurador). Estou tendo que re-escrever praticamente todo o c&amp;#243;digo. Al&amp;#233;m de que, o Shader Designer utiliza uma s&amp;#233;rie de c&amp;#243;digos fontes e de bibliotecas de terceiros (vide abaixo) que tamb&amp;#233;m est&amp;#227;o sendo portados. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digos Fontes de terceiros&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;a) 3DLabs GLSL Open Source Compiler &lt;br /&gt;&lt;br /&gt;b) Algumas fun&amp;#231;&amp;#245;es da &amp;quot;Matrix and Quaternion fAQ&amp;quot; &lt;br /&gt;&lt;br /&gt;c) AVI exporter &lt;br /&gt;&lt;br /&gt;d) GLEW Extensions manager.&lt;br /&gt;&lt;br /&gt;e) MeshMender da Nvidia&lt;br /&gt;&lt;br /&gt;f) DEV-IL&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Bibliotecas de terceiros&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;a) Compona's SyntaxBox. &lt;br /&gt;&lt;br /&gt;b) Flexporter&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;15/12/2008&lt;/h2&gt;Nestas &amp;#250;ltimas semanas escrevi e apresentei um trabalho acad&amp;#234;mico sobre o assunto. A apresenta&amp;#231;&amp;#227;o pode ser obtida &lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=51900';"&gt;aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Tamb&amp;#233;m foram acrescentadas novas funcionalidades:
&lt;ul&gt;&lt;li&gt;Permite ao usu&amp;#225;rio optar por depurar:
&lt;ul&gt;&lt;li&gt;Apenas o shader;&lt;/li&gt;
&lt;li&gt;Apenas o programa OpenGL hospedeiro;&lt;/li&gt;
&lt;li&gt;Ambos.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;ul&gt;&lt;li&gt;Permite visualizar o valor atualizado das vari&amp;#225;veis que j&amp;#225; foram depuradas&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Nas pr&amp;#243;ximas semanas, vou iniciar o estudo sobre desenvolvimento de plugins e come&amp;#231;ar a integra&amp;#231;&amp;#227;o da ferramenta.&lt;br /&gt;
&lt;h2&gt;30/11/2008&lt;/h2&gt;Como dito no post anterior, foram muitas as dificuldades encontradas na utiliza&amp;#231;&amp;#227;o de extens&amp;#245;es para captura de dados da placa gr&amp;#225;fica.&lt;br /&gt;Para que outras pessoas que necessitem utilizar estas extens&amp;#245;es n&amp;#227;o enfrentem o mesmo problema (principalmente pela falta de documenta&amp;#231;&amp;#227;o e de exemplos de uso), coloquei na p&amp;#225;gina &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Capturing%20Data%20From%20Graphics%20Hardware&amp;referringTitle=Blog"&gt;Capturing Data From Graphics Hardware&lt;/a&gt;, uma explica&amp;#231;&amp;#227;o das extens&amp;#245;es utilizadas com exemplos. &lt;br /&gt;&lt;br /&gt;O depurador foi aprimorado. Agora &amp;#233; poss&amp;#237;vel n&amp;#227;o apenas ver o resultado da vari&amp;#225;vel que est&amp;#225; sendo depurada, mas tamb&amp;#233;m das fun&amp;#231;&amp;#245;es pr&amp;#233;-definidas da OpenGL Al&amp;#233;m disto, foi escrito um trabalho acad&amp;#234;mico sobre o assunto, que ap&amp;#243;s sua apresenta&amp;#231;&amp;#227;o, tamb&amp;#233;m estar&amp;#225; dispon&amp;#237;vel aqui no CodePlex.&lt;br /&gt;&lt;br /&gt;Em breve tamb&amp;#233;m estarei disponibilizando um realease do depurador.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;30/10/2008 - Finishing the Debugger&lt;/h2&gt;Durante este m&amp;#234;s me foquei em terminar o depurador GLSL.&lt;br /&gt;Foram muitas as dificuldades encontradas, principalmente na utiliza&amp;#231;&amp;#227;o de extens&amp;#245;es para capturar a sa&amp;#237;da dos processadores de v&amp;#233;rtices e de fragmentos.&lt;br /&gt;Foram implementados 3 m&amp;#243;dulos:
&lt;ul&gt;&lt;li&gt;Wrapper OpenGL -&amp;gt; respons&amp;#225;vel por capturar as opera&amp;#231;&amp;#245;es OpenGL realizadas pelo programa OpenGL hospedeiro e inserir os c&amp;#243;digos necess&amp;#225;rios para depura&amp;#231;&amp;#227;o;&lt;/li&gt;
&lt;li&gt;Parser GLSL -&amp;gt; respons&amp;#225;vel por re-escrever o c&amp;#243;digo do shader GLSL de modo a inserir as vari&amp;#225;veis de depura&amp;#231;&amp;#227;o necess&amp;#225;rias&lt;/li&gt;
&lt;li&gt;Interfce Gr&amp;#225;fica -&amp;gt; respons&amp;#225;vel por interligar e utilizar os resultados obtidos nos demais m&amp;#243;dulos, al&amp;#233;m de, &amp;#233; claro, ser a interface com o usu&amp;#225;rio.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Este trabalho foi apresentado no &lt;a href="http://www.propesq.ufrgs.br/sic2008/index.htm" class="externalLink"&gt;XX Sal&amp;#227;o de IC - UFRGS&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. A apresenta&amp;#231;&amp;#227;o pode ser baixada &lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=47908';"&gt;aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Para as pr&amp;#243;ximas semanas pretendo continuar trabalhando no aprimoramento da ferramenta e escrever um documento mais detalhado sobre seu desenvolvimento.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;30/09/2008 - GLSL Debugger&lt;/h2&gt;
Passei algum tempo sem postar no blog. Durante este tempo estava trabalhando em uma nova etapa do projeto, o desenvolvimento de um plugin de depura&amp;#231;&amp;#227;o de GLSL para o Visual Studio. Maiores detalhes do andamento e da descri&amp;#231;&amp;#227;o desta etapa podem ser encontrados em &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=GLSL%20Debugger&amp;referringTitle=Blog"&gt;GLSL Debugger&lt;/a&gt;.&lt;br /&gt;
&lt;h2&gt;18/08/2008&lt;/h2&gt;GLSL n&amp;#227;o possui suporte &amp;#224; cast impl&amp;#237;cito (ex: vec4 color = 0.5;) assim, acrescentei o cast explicito (ex: vec4 color = vec4(0.5); )&lt;br /&gt;&lt;br /&gt;Continuei com os testes do programa. A principal dificuldade encontrada nos testes &amp;#233; a valida&amp;#231;&amp;#227;o. Por enquanto, o m&amp;#233;todo utilizado para os testes consiste em pegar um c&amp;#243;digo HLSL v&amp;#225;lido, converter e testar em um compilador GLSL se o c&amp;#243;digo gerado &amp;#233; v&amp;#225;lido ou n&amp;#227;o. Se n&amp;#227;o for, o programa &amp;#233; corrigido. Ou seja, por falta de uma BNF oficial da HLSL, nossos testes s&amp;#227;o baseados em exemplos. O que n&amp;#227;o &amp;#233; o ideal. A id&amp;#233;ia &amp;#233; que a pr&amp;#243;xima etapa de testes seja realizada comparando as imagens geradas. Ou seja, ser&amp;#227;o obtidas imagens executando o shader HLSL e estas ser&amp;#227;o comparadas com as imagens obtidas atrav&amp;#233;s da execu&amp;#231;&amp;#227;o do shader GLSL. A diferen&amp;#231;a entre estas imagens nos dir&amp;#225; o percentual de erro obtido na convers&amp;#227;o. &amp;#201; mais uma forma de validar o programa, por&amp;#233;m, o fato dos testes serem baseados em exemplos persiste. Para que este fator n&amp;#227;o seja t&amp;#227;o relevante, estamos utilizando uma gama variada de exemplos.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;04/08/2008&lt;/h2&gt;Como o programa estava dispon&amp;#237;vel apenas em vers&amp;#245;es de linha de comando, desenvolvi uma vers&amp;#227;o que apresenta uma interface gr&amp;#225;fica simplificada. Com esta interface, basta o usu&amp;#225;rio carregar o c&amp;#243;digo HLSL e clicar em converter. Os c&amp;#243;digos s&amp;#227;o exibidos lado &amp;#224; lado, facilitando a visualiza&amp;#231;&amp;#227;o pelo usu&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;Esta interface apresenta um limitante, que &amp;#233; o fato de ser compat&amp;#237;vel apenas com sistemas Windows. Por&amp;#233;m, em breve, pretendo desenvolver uma vers&amp;#227;o compat&amp;#237;vel com outros sistemas.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;24/07/2008&lt;/h2&gt;GLSL n&amp;#227;o apresenta suporte ao comando &amp;quot;Switch&amp;quot;. Desta forma, fiz uma fun&amp;#231;&amp;#227;o que substitui este comando por &amp;quot;If..else&amp;quot;.&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;        switch ( teste ) {
    			case 0: k++; return teste; 
    			case 1: return teste; 
    			case 2: t++; return teste; 
    			default: { 
    				teste++;
       			} 
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;      if (teste == 0) { k++; return teste; }
      else if (teste == 1) { return teste;}
      else if (teste == 2) { t++; return teste; }
      else { teste++;  }
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;GLSL n&amp;#227;o permite atribui&amp;#231;&amp;#245;es para elementos dos vetores, se estes vetores forem vari&amp;#225;veis to tipo &amp;quot;varying&amp;quot;. Ent&amp;#227;o, fiz uma fun&amp;#231;&amp;#227;o que cria uma vari&amp;#225;vel tempor&amp;#225;ria, efetua a atribui&amp;#231;&amp;#227;o e ent&amp;#227;o atribui o valor &amp;#224; vari&amp;#225;vel original.&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;  float4 MyShader( float2 Tex : TEXCOORD0 ) : COLOR0
{
    float4 Color;
    
    Color = float4(1.0,1.0,1.0,1.0);
    Color.a;
    Color.a = 0.1;
    Color.rgb = float3(0.5f);

    Tex.y = Tex.y + (sin(timeraslow)*0.01);
    Tex.x = Tex.x + (cos(timeraslow)*0.01);
    Color = tex2D( g_samSrcColor, Tex.xy);

    Color -= tex2D( g_samSrcColor, Tex.xy-0.001)*2.0f;
    Color += tex2D( g_samSrcColor, Tex.xy+0.001)*2.0f;
    Color.rgb = float3((Color.r+Color.g+Color.b)/3.0f);   	
   	
    return Color;
}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt; varying vec2 Tex;

void main( )
{
    vec4 Color;
    
    Color = vec4(1.0,1.0,1.0,1.0);
    Color.a;
    Color.a = 0.1;
    Color.rgb = vec3(0.5); //n&amp;#227;o necessita de vari&amp;#225;vel tempor&amp;#225;ria pois n&amp;#227;o &amp;#233; varying

    vec2 tempTex = Tex; //como Tex era varying foi criada uma vari&amp;#225;vel tempor&amp;#225;ria 

    tempTex.y = Tex.y + (sin(timeraslow)*0.01);
    Tex=tempTex;
    tempTex.x = Tex.x + (cos(timeraslow)*0.01);
    Tex=tempTex;
    Color = tex2D( g_samSrcColor, Tex.xy);

    Color -= tex2D( g_samSrcColor, Tex.xy-0.001)*2.0;
    Color += tex2D( g_samSrcColor, Tex.xy+0.001)*2.0;
    Color.rgb = vec3((Color.r+Color.g+Color.b)/3.0));   	
   	
    gl_FragColor = Color;
}
&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;09/07/2008&lt;/h2&gt;Acrescentei a convers&amp;#227;o das fun&amp;#231;&amp;#245;es intr&amp;#237;nsicas. Para as fun&amp;#231;&amp;#245;es intr&amp;#237;nsicas de HLSL que n&amp;#227;o s&amp;#227;o suportadas pela GLSL (vide &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Differences%20Between%20HLSL%20and%20GLSL&amp;referringTitle=Blog"&gt;Differences Between HLSL and GLSL&lt;/a&gt;), &amp;#233; emitida uma mensagem de aviso ao usu&amp;#225;rio.  GLSL tamb&amp;#233;m n&amp;#227;o suporta a letra 'f' ap&amp;#243;s um n&amp;#250;mero do tipo float (ex: 1.0f), ent&amp;#227;o, inseri uma fun&amp;#231;&amp;#227;o que remove este 'f' do n&amp;#250;mero. &lt;br /&gt;&lt;br /&gt;Iniciei tamb&amp;#233;m a fase de testes do programa. Para isto estou utilizando os shaders  &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Parsing%20Shaders&amp;referringTitle=Blog"&gt;Parsing Shaders&lt;/a&gt;. Ap&amp;#243;s converter, executo o arquivo gerado no software &lt;a href="http://www.opengl.org/sdk/tools/ShaderDesigner" class="externalLink"&gt;Shader Designer&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. Este software &amp;#233; um editor/compilador de GLSL. Assim, atrav&amp;#233;s de sua sa&amp;#237;da, posso verificar se o c&amp;#243;digo GLSL gerado &amp;#233; v&amp;#225;lido ou n&amp;#227;o e corrigir os problemas encontrados.&lt;br /&gt;&lt;br /&gt;A vers&amp;#227;o mais atual dos fontes do projeto encontra-se &lt;a href="http://www.codeplex.com/hl2glsl/SourceControl/ListDownloadableCommits.aspx" class="externalLink"&gt;dispon&amp;#237;vel&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;04/07/2008&lt;/h2&gt;Fiz algumas altera&amp;#231;&amp;#245;es na gram&amp;#225;tica e acrescentei novas fun&amp;#231;&amp;#245;es para tratar estas altera&amp;#231;&amp;#245;es.&lt;br /&gt;&lt;br /&gt;Altera&amp;#231;&amp;#245;es na gram&amp;#225;tica:&lt;br /&gt;*Reconhecimento do par&amp;#226;metro &amp;quot;: Register&amp;quot;;&lt;br /&gt;*Reconhecimento do par&amp;#226;metro &amp;quot;: Packoffset&amp;quot;;&lt;br /&gt;*Reconhecimento do operador un&amp;#225;rio &amp;quot;!&amp;quot;;&lt;br /&gt;*Reconhecimento do tipo &amp;quot;uint&amp;quot;.&lt;br /&gt;&lt;br /&gt;GLSL n&amp;#227;o apresenta suporte para acesso &amp;#224; registradores. Assim, os par&amp;#226;metros &amp;quot;register&amp;quot; e &amp;quot;packoffset&amp;quot; n&amp;#227;o podem ser utilizados. A medida adotada para solucionar este problema &amp;#233; avisar ao usu&amp;#225;rio deste fato e perguntar se ele deseja remover estes par&amp;#226;metros. Caso ele opte por n&amp;#227;o remover, um aviso de que o c&amp;#243;digo gerado ser&amp;#225; inconsistente &amp;#233; emitido.&lt;br /&gt;&lt;br /&gt;O caso do tipo &amp;quot;uint&amp;quot; &amp;#233; similar, pois tamb&amp;#233;m n&amp;#227;o &amp;#233; suportado pela GLSL. S&amp;#243; que ao inv&amp;#233;s de remover a vari&amp;#225;vel, a op&amp;#231;&amp;#227;o dada ao usu&amp;#225;rio &amp;#233; a de troc&amp;#225;-lo pelo tipo int. &lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;18/06/2008&lt;/h2&gt;Passei a utilizar o Source Code Client do CodePlex para disponibilizar o c&amp;#243;digo fonte.&lt;br /&gt;&lt;br /&gt;Acrescentei as fun&amp;#231;&amp;#245;es para tratar &amp;quot;return&amp;quot; e o tipo da fun&amp;#231;&amp;#227;o &amp;quot;main&amp;quot;.&lt;br /&gt;&lt;br /&gt;Em GLSL &amp;#233; necess&amp;#225;rio uma fun&amp;#231;&amp;#227;o void main() que &amp;#233; de onde iniciar&amp;#225; a execu&amp;#231;&amp;#227;o.  Em HLSL, isto n&amp;#227;o &amp;#233; necess&amp;#225;rio.&lt;br /&gt;Assim, &amp;#233; preciso substituir o nome da fun&amp;#231;&amp;#227;o em HLSL por &amp;quot;main&amp;quot; e o tipo da fun&amp;#231;&amp;#227;o por void. O tipo da fun&amp;#231;&amp;#227;o deve ser salvo pois ele ser&amp;#225; utilizado na sa&amp;#237;da da fun&amp;#231;&amp;#227;o.  &lt;br /&gt;&lt;br /&gt;Como a fun&amp;#231;&amp;#227;o em GLSL &amp;#233; do tipo void, ela n&amp;#227;o tem mais o &amp;quot;return&amp;quot;.  Sua sa&amp;#237;da vai ser determinada de acordo com o tipo e os par&amp;#226;metros sem&amp;#226;nticos da fun&amp;#231;&amp;#227;o original, &lt;br /&gt;&lt;br /&gt;Ex: &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;float4 pixelShader( float4 color):COLOR
{
          float4 teste =float4(0,1,0,0);
          float4 tes   = color + teste;

          return tes;
} &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;varying vec4 color;

void main() { 

	vec4 teste = vec4(0,1,0,0);
	vec4 tes   = color + teste;
	
	gl_FragColor = vec4(tes) ;  
} &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;02/06/2008&lt;/h2&gt;
Disponibilizei os fontes em desenvolvimento do projeto na sess&amp;#227;o Releases nas vers&amp;#245;es de projeto para Mono e Visual Studio.&lt;br /&gt;
&lt;h2&gt;30/05/2008&lt;/h2&gt;
Comecei a entender mais a fundo o projeto. Para isto, estudei HLSL e aprendi as principais diferen&amp;#231;as entre as duas linguagens.&lt;br /&gt;Portei o projeto para o Visual Studio 2008. E fiz uma an&amp;#225;lise do que j&amp;#225; foi feito e do que ainda faltava fazer.&lt;br /&gt;Acrescentei as &amp;quot;System-value semantics&amp;quot; &amp;#224; gramatica. Estas sem&amp;#226;nticas est&amp;#227;o dispon&amp;#237;veis apenas no &lt;a href="http://msdn.microsoft.com/en-us/library/bb509647(VS.85).aspx#System_Value" class="externalLink"&gt;Direct 3D 10&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;15/05/2008&lt;/h2&gt;O projeto &amp;#233; desenvolvido em C#. Como n&amp;#227;o conhecia a linguagem, aproveitei para aprender em um curso.&lt;br /&gt;&lt;br /&gt;Este curso faz parte do programa Students2Business, criado pela Microsoft e desenvolvido pelos Centros de Inova&amp;#231;&amp;#227;o e institui&amp;#231;&amp;#245;es de ensino parceiras. Resumidamente: o programa &amp;#233; gratu&amp;#237;to, o aluno pode escolher entre aulas de desenvolvimento ou de infra-estrutura de TI e &amp;#233; divido em 3 etapas. Ao final de cada etapa h&amp;#225; uma prova classificat&amp;#243;ria para a etapa seguinte. As etapas 2 e 3 possuem dura&amp;#231;&amp;#227;o de 40hs. Ao final da terceira etapa, os alunos que apresentarem os melhores projetos finais podem realizar gratuitamente provas de certifica&amp;#231;&amp;#227;o Microsoft e todos os alunos que concluirem as 3 etapas ter&amp;#227;o direito a participar do evento de formatura. Maiores informa&amp;#231;&amp;#245;es sobre o programa em &lt;a href="http://proform.msdnbrasil.tempsite.ws/public/Default.aspx" class="externalLink"&gt;http://proform.msdnbrasil.tempsite.ws/public/Default.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;30/04/2008&lt;/h2&gt;
Ol&amp;#225;!&lt;br /&gt;&lt;br /&gt;Me chamo B&amp;#225;rbara e entrei no projeto para substituir o Vitor, que se afastou para fazer doutorado. Como ele, vou utilizar este espa&amp;#231;o para periodicamente publicar os avan&amp;#231;os do projeto.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;21/03/2008&lt;/h2&gt;
Nesta semana terminei a separa&amp;#231;&amp;#227;o das fun&amp;#231;&amp;#245;es em arquivos diferentes e iniciei algumas convers&amp;#245;es de nomes de vari&amp;#225;veis de acordo com um contexto sem&amp;#226;ntico. &lt;br /&gt;&lt;br /&gt;Por exemplo, enquanto em HLSL temos: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void main(
        float4 position   : POSITION, 
        float3 normal      : NORMAL, 
	float2 uv : TEXCOORD0,
	float3 lightDir : TEXCOORD1,
	float3 eyeDir : TEXCOORD2,
	float3 spotDir : TEXCOORD3,
	float3 lightDir1 : TEXCOORD4,
	float3 spotDir1 : TEXCOORD5,
	float4 shadowUV1 : TEXCOORD6,
	float4 shadowUV2 : TEXCOORD7)
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Em GLSL teremos: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
varying vec3 tangentEyeDir;
varying vec3 tangentLightDir[2];
varying vec3 tangentSpotDir[2];
varying vec4 shadowUV[2]; 
void main() { ... }
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;uv, position e normal no HLSL seriam as vari&amp;#225;veis pr&amp;#233;-definidas gl_TexCoord[0], gl_Vertex e gl_Normal  no GLSL. &lt;br /&gt;
&lt;h2&gt;14/03/2008&lt;/h2&gt;
Nesta semana comecei a construir o separador de fun&amp;#231;&amp;#245;es. De um arquivo HLSL pode-se gerar v&amp;#225;rios GLSL. Para tal utilizo o grafo de depend&amp;#234;ncias das fun&amp;#231;&amp;#245;es declaradas no arquivo e em seus includes para separar as fun&amp;#231;&amp;#245;es corretamente, levando para o arquivo correto a formata&amp;#231;&amp;#227;o desejada e os coment&amp;#225;rios pertinentes a ela.  &lt;br /&gt;
&lt;h2&gt;07/03/2008&lt;/h2&gt;
Enquanto o HLSL permite v&amp;#225;rias entradas de execu&amp;#231;&amp;#227;o, ou seja, v&amp;#225;rias fun&amp;#231;&amp;#245;es main, o GLSL s&amp;#243; permite uma e exige o nome main. Desta forma, esta semana, trabalhei na cria&amp;#231;&amp;#227;o de um grafo de chamadas de fun&amp;#231;&amp;#245;es, para determinar quais fun&amp;#231;&amp;#245;es est&amp;#227;o sendo utilizadas para cada fun&amp;#231;&amp;#227;o de entrada no HLSL. Com esse grafo, poderei colocar cada fun&amp;#231;&amp;#227;o de entrada do HLSL em um arquivo diferente, levando tamb&amp;#233;m suas fun&amp;#231;&amp;#245;es dependentes. &lt;br /&gt;
&lt;h2&gt;29/02/2008&lt;/h2&gt;
Nesta semana trabalhei com a migra&amp;#231;&amp;#227;o da declara&amp;#231;&amp;#227;o de vari&amp;#225;veis uniform e varying, de uma fun&amp;#231;&amp;#227;o para o contexto do arquivo. &lt;br /&gt;&lt;br /&gt;Do HLSL:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void funcao(
    // parameters 
    float4 position,
    uniform float4 lightPosition, // object space 
    uniform float4x4 texViewProj2) {..}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para o GLSL &lt;br /&gt;&lt;pre&gt;
// parameters 
uniform float4 lightPosition; // object space 
uniform float4x4 texViewProj2;

void funcao(
     float4 position
) {..}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Migra&amp;#231;&amp;#227;o simples, mas trabalhosa quando se tem uma &amp;#225;rvore de Tokens sem ignorar espa&amp;#231;os, coment&amp;#225;rios, novas linhas e tabula&amp;#231;&amp;#245;es. Acabei tento muita dificuldade em identificar os coment&amp;#225;rios relevantes que deveriam ser movidos juntamente com o par&amp;#226;metro.&lt;br /&gt;
&lt;h2&gt;22/02/2008&lt;/h2&gt;
Ol&amp;#225; a todos. &lt;br /&gt;&lt;br /&gt;Neste espa&amp;#231;o vou publicar os avan&amp;#231;os do projeto semanalmente. &lt;br /&gt;&lt;br /&gt;Nesta &amp;#250;ltima semana testei a &lt;a href="http://OGRE" class="externalLink"&gt;http://www.ogre3d.org/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; como arquitetura para os testes do projeto. Ao converter shaders de HLSL para GLSL, &amp;#233; necess&amp;#225;rio tamb&amp;#233;m converter o c&amp;#243;digo fonte do programa que os usa, da API do DirectX para a da OpenGL. Esta parte n&amp;#227;o &amp;#233; coberta por este projeto, portanto &amp;#233; manual. &lt;br /&gt;&lt;br /&gt;A OGRE &amp;#233; uma engine que permite o uso de shaders HLSL, Cg e GLSL de maneira unificada, removendo os links diretos ao DirectX ou ao OpenGL. Usando-a, n&amp;#227;o perderemos tempo migrando o c&amp;#243;digo fonte dos testes, apenas com os testes dos shaders. &lt;br /&gt;&lt;br /&gt;Tamb&amp;#233;m desenvolvi uma parte do conversor: 
&lt;ol&gt;&lt;li&gt;A troca da fun&amp;#231;&amp;#227;o &amp;quot;mul&amp;quot; pelo &amp;quot;*&amp;quot;&lt;/li&gt;
&lt;li&gt;A invers&amp;#227;o de par&amp;#226;metros na fun&amp;#231;&amp;#227;o &amp;quot;cross&amp;quot;&lt;/li&gt;
&lt;li&gt;A remo&amp;#231;&amp;#227;o de par&amp;#226;metros na fun&amp;#231;&amp;#227;o &amp;quot;main&amp;quot;&lt;/li&gt;&lt;/ol&gt;
&lt;br /&gt;E estudei algumas propriedades da representa&amp;#231;&amp;#227;o de matrizes das duas linguagens. Apesar dos elementos descritos na p&amp;#225;gina &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Differences%20Between%20HLSL%20and%20GLSL&amp;referringTitle=Blog"&gt;Differences Between HLSL and GLSL&lt;/a&gt;, ainda tenho d&amp;#250;vidas sobre o modo de trabalho com as matrizes, especialmente se devo ou n&amp;#227;o transp&amp;#244;-las.  &lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Thu, 12 Nov 2009 18:26:35 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Blog 20091112062635P</guid></item><item><title>Updated Wiki: OpenCL Tutorials</title><link>http://hl2glsl.codeplex.com/wikipage?title=OpenCL Tutorials&amp;version=6</link><description>&lt;div class="wikidoc"&gt;Ol&amp;#225;,&lt;br /&gt;estes s&amp;#227;o os tutorials dispon&amp;#237;veis at&amp;#233; agora:
&lt;ul&gt;&lt;li&gt;&lt;a href="http://hl2glsl.codeplex.com/wikipage?title=OpenCL%20Tutorials%20-%201&amp;referringTitle=OpenCL%20Tutorials"&gt;OpenCL Tutorials - 1&lt;/a&gt; (quickstart)
&lt;ul&gt;&lt;li&gt;vers&amp;#227;o em pdf: &lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=92629';"&gt;OpenCL Tutorials1.pdf&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;At&amp;#233;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Thu, 12 Nov 2009 18:14:09 GMT</pubDate><guid isPermaLink="false">Updated Wiki: OpenCL Tutorials 20091112061409P</guid></item><item><title>Updated Wiki: OpenCL Tutorials</title><link>http://hl2glsl.codeplex.com/wikipage?title=OpenCL Tutorials&amp;version=5</link><description>&lt;div class="wikidoc"&gt;Ol&amp;#225;,&lt;br /&gt;estes s&amp;#227;o os tutorials dispon&amp;#237;veis at&amp;#233; agora:
&lt;ul&gt;&lt;li&gt;&lt;a href="http://hl2glsl.codeplex.com/wikipage?title=OpenCL%20Tutorials%20-%201&amp;referringTitle=OpenCL%20Tutorials"&gt;OpenCL Tutorials - 1&lt;/a&gt; (quickstart)
&lt;ul&gt;&lt;li&gt;vers&amp;#227;o em pdf: &lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=92146';"&gt;OpenCL Tutorials1.pdf&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;At&amp;#233;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Tue, 10 Nov 2009 18:43:03 GMT</pubDate><guid isPermaLink="false">Updated Wiki: OpenCL Tutorials 20091110064303P</guid></item><item><title>Updated Wiki: OpenCl Tutorials - 1</title><link>http://hl2glsl.codeplex.com/wikipage?title=OpenCl Tutorials - 1&amp;version=32</link><description>&lt;div class="wikidoc"&gt;Ol&amp;#225; a todos,&lt;br /&gt;este &amp;#233; meu primeiro tutorial sobre OpenCL, e espero que seja &amp;#250;til.&lt;br /&gt;N&amp;#227;o falarei aqui sobre OpenCL em si, j&amp;#225; que h&amp;#225; por a&amp;#237; suficientes introdu&amp;#231;&amp;#245;es a OpenCL. Come&amp;#231;arei o tutorial falando um pouco sobre o modelo de execu&amp;#231;&amp;#227;o de OpenCL, mas ser&amp;#225; algo breve. Teremos tempo mais tarde para isso.&lt;br /&gt;Neste tutorial, o que eu gostaria de providenciar &amp;#233; um &lt;i&gt;quickstart&lt;/i&gt; para que fique mais tranquilo come&amp;#231;ar a usar e a fazer testes em OpenCL.&lt;br /&gt;&lt;br /&gt;Os c&amp;#243;digos deste tutorial encontram-se aqui:
&lt;ul&gt;&lt;li&gt;&lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=86739';"&gt;main.cpp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=86740';"&gt;vector_add.cl&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Um programa OpenCL se divide em duas partes: a execu&amp;#231;&amp;#227;o do &lt;i&gt;host&lt;/i&gt;, que &amp;#233; a execu&amp;#231;&amp;#227;o na CPU, como j&amp;#225; a conhecemos. Nesta etapa apenas s&amp;#227;o adicionadas algumas instru&amp;#231;&amp;#245;es para preparar a execu&amp;#231;&amp;#227;o do &lt;i&gt;device&lt;/i&gt;.&lt;br /&gt;A outra parte, a parte do &lt;i&gt;device&lt;/i&gt;, refere-se &amp;#224; computa&amp;#231;&amp;#227;o que ocorrer&amp;#225;, no nosso caso, na GPU. Para esta deveremos nos acostumar com alguns conceitos b&amp;#225;sicos. O primeiro deles &amp;#233; o de &lt;i&gt;kernel&lt;/i&gt;. Um &lt;i&gt;kernel&lt;/i&gt;, como j&amp;#225; foi citado no blog, &amp;#233; uma fun&amp;#231;&amp;#227;o que executa no device. Uma caracter&amp;#237;stica importante do modelo &amp;#233; que temos uma execu&amp;#231;&amp;#227;o SIMT (Single Instruction Multiple Thread), ou seja, o mesmo kernel &amp;#233; executado simultaneamente com dados diferentes.&lt;br /&gt;Aceita essa id&amp;#233;ia, passamos agora para alguns conceitos auxiliares:
&lt;ul&gt;&lt;li&gt;&lt;b&gt;work-item&lt;/b&gt;: sempre que um kernel &amp;#233; lan&amp;#231;ado, cada instancia em execu&amp;#231;&amp;#227;o desse kernel torna-se um work-item. Work-items s&amp;#227;o identificados por um &amp;#237;ndice que pode ser acessado de dentro do kernel;&lt;/li&gt;&lt;/ul&gt;
Na arquitetura NVIDIA, cada work-item &amp;#233; mapeado para uma CUDA thread;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;work-group&lt;/b&gt;: &amp;#233; como os work-items s&amp;#227;o agrupados. &amp;#201; importante ressaltar que esse agrupamento &amp;#233; muito mais importante do que pode parecer a primeira vista, dado que todos os work-items pertencentes a um work-group s&amp;#227;o executados na mesma &lt;i&gt;Compute Unit&lt;/i&gt; (que s&amp;#227;o mapeados, na arquitetura NVIDIA, para Scalar Processors (SPs)), o que lhes permite interagir entre si de forma muito mais eficiente. Work-groups s&amp;#227;o mapeados, em CUDA, para &lt;i&gt;thread blocks&lt;/i&gt;;&lt;/li&gt;&lt;/ul&gt;
Work-groups possuem, assim como os work-items, IDs &amp;#250;nicos que podem ser acessados de dentro do kernel;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;NDRange&lt;/b&gt;: um NDRange &amp;#233; um grid N-dimensional (com N = 1, 2 ou 3) de work-groups. Eles tamb&amp;#233;m s&amp;#227;o acessados por um ID;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=86520" alt="opencl-execution-model.JPG" title="opencl-execution-model.JPG" /&gt;&lt;br /&gt;Este &amp;#233; um exemplo de NDRange (retirado da especifica&amp;#231;&amp;#227;o liberada pelo Khronos Group).&lt;br /&gt;&lt;br /&gt;OK. Acho que &amp;#233; o suficiente por hoje. Mais tarde teremos a oportunidade de estudar mais a fundo essas caracter&amp;#237;sticas da linguagem e da arquitetura. Por hora &amp;#233; tudo com o qual devemos nos preocupar.&lt;br /&gt;Agora gostaria de desenvolver aqui um primeiro exemplo pr&amp;#225;tico. Trata-se de um programa muito simples, que computa a soma de dois vetores.&lt;br /&gt;Este exemplo &amp;#233; fortemente baseado no exemplo an&amp;#225;logo da NVIDIA, que vem junto com o SDK do OpenCl.&lt;br /&gt;
&lt;h3&gt;Kernel&lt;/h3&gt;Certo, vamos come&amp;#231;ar com a parte f&amp;#225;cil da hist&amp;#243;ria: programando o kernel.&lt;br /&gt;Suponhamos que estiv&amp;#233;ssemos interessados em fazer uma fun&amp;#231;&amp;#227;o comum para calcular a soma entre dois vetores. Ela seria mais ou menos assim:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void vector_add_golden (const float * const srcA,
                                     const float * const srcB,
                                     float * const golden) {
	for (int i = 0; i &amp;lt; iNumElements; i++)
		golden[i] = srcA[i] + srcB[i];
}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O que temos a&amp;#237; &amp;#233; um la&amp;#231;o que itera por todos os elementos do vetor e soma seus valores, colocando o resultado no terceiro vetor.&lt;br /&gt;Se quis&amp;#233;ssemos fazer isso em OpenCL, escrever&amp;#237;amos uma fun&amp;#231;&amp;#227;o que somasse dois vetores, escreveriamos a fun&amp;#231;&amp;#227;o que soma um elemento do vetor, e esse elemento seria o indice da instancia do kernel em execu&amp;#231;&amp;#227;o. Complicado? Vamos ver um exemplo:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
__kernel &lt;span style="color:Blue;"&gt;void&lt;/span&gt; vector_add (__global &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;float&lt;/span&gt; * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; v1,
			 __global &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;float&lt;/span&gt; * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; v2,
			 __global &lt;span style="color:Blue;"&gt;float&lt;/span&gt; * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; res,
			 __global &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;int&lt;/span&gt; n) {
	&lt;span style="color:Blue;"&gt;int&lt;/span&gt; idx = get_global_id(0);

	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (idx &amp;lt; n)
		 res[idx] = v1[idx] + v2[idx];
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Percebam que utilizamos a palavra reservada &lt;b&gt;__kernel__&lt;/b&gt; para especificar que trata-se de um kernel.&lt;br /&gt;Outro detalhe est&amp;#225; em&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	&lt;span style="color:Blue;"&gt;int&lt;/span&gt; idx = get_global_id(0);

&lt;/pre&gt;&lt;/div&gt;essa instru&amp;#231;&amp;#227;o coloca em 'idx' o ID da instancia do kernel em execu&amp;#231;&amp;#227;o.&lt;br /&gt;&lt;br /&gt;Em seguida o que fazemos &amp;#233; o seguinte: O kernel se pergunta: &amp;quot;Meu ID est&amp;#225; dentro dos limites do vetor?&amp;quot;. Caso afirmativo, ele computa a soma &lt;b&gt;desse&lt;/b&gt; elemento, e caso negativo nada &amp;#233; feito.&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;alguns detalhes adicionais: &lt;/li&gt;&lt;/ul&gt;
Esse kernel deve estar obrigat&amp;#243;riamente em um arquivo com extens&amp;#227;o &amp;quot;.cl&amp;quot;, que deve ser separado dos arquivos &amp;quot;.cpp&amp;quot; ou &amp;quot;.c&amp;quot; que contiverem c&amp;#243;digo a ser compilado.&lt;br /&gt;Nos arquivos &amp;quot;.cl&amp;quot; deve constar &lt;b&gt;apenas&lt;/b&gt; c&amp;#243;digo OpenCL, visto que o c&amp;#243;digo OpenCL &amp;#233; compilado em tempo de execu&amp;#231;&amp;#227;o e deve ser 'invocado' de algum lugar.&lt;br /&gt;
&lt;h3&gt;Inicializando...&lt;/h3&gt;Ok, alta agora apenas a prepara&amp;#231;&amp;#227;o para o lan&amp;#231;amento do kernel.&lt;br /&gt;Mas n&amp;#227;o sejamos t&amp;#227;o apressados. Vamos entrar agora na parte mais chata deste tutorial.&lt;br /&gt;OpenCL &amp;#233; uma linguagem de baixo n&amp;#237;vel, portanto nos cabe o trabalho de fazer grande parte das coisas que, por exemplo, CUDA faz por n&amp;#243;s.&lt;br /&gt;Mas vamos por partes. Precisaremos, inicialmente, dos headers necess&amp;#225;rios. Isso &amp;#233; facil:&lt;br /&gt;&lt;pre&gt;
#include &amp;lt;oclUtils.h&amp;gt;
&lt;/pre&gt;&lt;br /&gt;Este &amp;#233; um arquivo disponibilizado juntamente com os exemplos da NVIDIA, e que nos d&amp;#225; algumas fun&amp;#231;&amp;#245;es interessantes, mas que n&amp;#227;o &amp;#233; necess&amp;#225;rio.&lt;br /&gt;Ele inclui sozinho o arquivo &lt;i&gt;CL/cl.h&lt;/i&gt;, que &amp;#233;, esse sim, o verdadeiro necess&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;Faremos tamb&amp;#233;m algumas declara&amp;#231;&amp;#245;es adicionais:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
#include &amp;lt;iostream&amp;gt;

&lt;span style="color:Blue;"&gt;#define&lt;/span&gt; NUM 11444777

&lt;span style="color:Blue;"&gt;using&lt;/span&gt; &lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; std;

&lt;span style="color:Green;"&gt;/* Estes s&amp;#227;o, em ordem, o nome do arquivo em que se encontra nosso kernel,
 * o n&amp;#250;mero de elementos da computa&amp;#231;&amp;#227;o e um inteiro que ser&amp;#225; utilizado para
 * verifica&amp;#231;&amp;#227;o de erros;
 */&lt;/span&gt;
&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;* cSourceFile = &lt;span style="color:#A31515;"&gt;&amp;quot;vector_add.cl&amp;quot;&lt;/span&gt;;
cl_int iNumElements = NUM;
cl_int error = 0;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Ok, mais uma tarefa f&amp;#225;cil agora: alocar a mem&amp;#243;ria do host, inicializ&amp;#225;-la e computar no host para futura verifica&amp;#231;&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Green;"&gt;/* Aqui s&amp;#227;o alocadas as vari&amp;#225;veis que residem na CPU. S&amp;#227;o elas os dois vetores a serem somados,
	 * e os dois vetores com os resultados da computa&amp;#231;&amp;#227;o no host e no device;
	 */&lt;/span&gt;
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; srcA = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; srcB = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; golden = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; res = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	
	&lt;span style="color:Green;"&gt;/* Fazemos a devida inicializa&amp;#231;&amp;#227;o dos vetores a serem somados.
	 */&lt;/span&gt;
	&lt;span style="color:Blue;"&gt;for&lt;/span&gt; (&lt;span style="color:Blue;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; iNumElements; ++i) {
		srcA[i] = srcB[i] = i;
	}
	
	&lt;span style="color:Green;"&gt;/* Aqui fazemos o c&amp;#225;lculo da soma na CPU, para fins de verifica&amp;#231;&amp;#227;o.
	 */&lt;/span&gt;
	vector_add_golden(srcA, srcB, golden);
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Contexto e Command-queue&lt;/h3&gt;Muito bem, a esta altura j&amp;#225; estamos com tudo pronto para criar nosso contexto e nossa command-queue.&lt;br /&gt;Um contexto engloba todas as variaveis e os registradores, ou seja, o estado de uma computa&amp;#231;&amp;#227;o. A command-queue, por outro lado, &amp;#233; a fila de comandos que devem ser efetuados no programa.&lt;br /&gt;Para criar o contexto, utilizaremos a seguinte fun&amp;#231;&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_context clCreateContextFromType5 (cl_context_properties *properties,
						cl_device_type device_type,
						&lt;span style="color:Blue;"&gt;void&lt;/span&gt; (*pfn_notify)(&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; *errinfo,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; *private_info, size_t cb,
						&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data),
						&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data,
						cl_int *errcode_ret)
&lt;/pre&gt;&lt;/div&gt;Onde:
&lt;ul&gt;&lt;li&gt;&lt;i&gt;properties&lt;/i&gt; &amp;#233; um vetor de propriedades co contexto, que por hora ser&amp;#225; passado como NULL;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;cl&lt;/i&gt;device&lt;i&gt;type&lt;/i&gt; especifica o tipo do device. A tabela completa encontra-se na especifica&amp;#231;&amp;#227;o, utilizaremos CL&lt;i&gt;DEVICE&lt;/i&gt;TYPE_GPU, pois estamos criando o contexto na GPU;&lt;/li&gt;
&lt;li&gt;As proximas duas informa&amp;#231;&amp;#245;es tampouco ser&amp;#227;o importantes por hora, e ser&amp;#227;o passadas como NULL;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;errcode&lt;/i&gt;ret_ &amp;#233; o inteiro, que declaramos l&amp;#225; encima, que conter&amp;#225; o c&amp;#243;digo de um eventual erro;&lt;/li&gt;&lt;/ul&gt;
Se tudo der certo, ser&amp;#225; retornado CL_SUCCESS.&lt;br /&gt;&lt;br /&gt;Nosso c&amp;#243;digo fica ent&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        cl_context context = clCreateContextFromType (NULL, CL_DEVICE_TYPE_GPU, NULL, NULL, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando contexto&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Para criar a command-queue, precisaremos primeiramente da lista de &lt;i&gt;devices&lt;/i&gt; de nosso sistema. Para fazer isto, utilizaremos a fun&amp;#231;&amp;#227;o &lt;i&gt;clGetContextInfo&lt;/i&gt;, como pode ser visto abaixo:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Green;"&gt;// Estes s&amp;#227;o, respectivamente, o vetor de devices a ser preenchido e o tamanho em mem&amp;#243;ria desse vetor;&lt;/span&gt;
        cl_device_id *devices;
	size_t devices_size;
        &lt;span style="color:Green;"&gt;// Chamamos a fun&amp;#231;&amp;#227;o uma primeira vez, para conseguir o tamanho em mem&amp;#243;ria que deve ser alocado a devices;&lt;/span&gt;
	error = clGetContextInfo (context, CL_CONTEXT_DEVICES, 0, NULL, &amp;amp;devices_size);
        &lt;span style="color:Green;"&gt;// Alocamos o espaco necessario&lt;/span&gt;
	devices = (cl_device_id*) malloc (devices_size);
        &lt;span style="color:Green;"&gt;// E chamamos novamente a funcao para efetivamente colocar em 'devices' a informacao de todos os devices (no meu caso apenas uma GPU)&lt;/span&gt;
	error |= clGetContextInfo (context, CL_CONTEXT_DEVICES, devices_size, devices, 0);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro pegando informacoes do contexto;&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Muito bem, j&amp;#225; estamos prontos para a cria&amp;#231;&amp;#227;o da command_queue:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        cl_command_queue queue = clCreateCommandQueue (context, *devices, 0, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando command_queue&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Alocando mem&amp;#243;ria no device&lt;/h3&gt;
Ok, j&amp;#225; criamos as estruturas necess&amp;#225;rias para gerenciar a execu&amp;#231;&amp;#227;o OpenCL. Vamos agora alocar os vetores para serem somados na GPU, e em seguida invocar o kernel.&lt;br /&gt;Em OpenCl, temos que alocar um buffer, que &amp;#233; um espa&amp;#231;o de mem&amp;#243;ria a ser alocado em um contexto.&lt;br /&gt;A aloca&amp;#231;&amp;#227;o tem a seguinte assinatura:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_mem clCreateBuffer (cl_context context,
			cl_mem_flags flags,
			size_t size,
			&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *host_ptr,
			cl_int *errcode_ret)
&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;As flags podem ser:
&lt;ul&gt;&lt;li&gt;CL_MEM_READ_WRITE&lt;/li&gt;
&lt;li&gt;CL_MEM_WRITE_ONLY&lt;/li&gt;
&lt;li&gt;CL_MEM_READ_ONLY&lt;/li&gt;
&lt;li&gt;CL_MEM_USE_HOST_PTR&lt;/li&gt;
&lt;li&gt;CL_MEM_ALLOC_HOST_PTR&lt;/li&gt;
&lt;li&gt;CL_MEM_COPY_HOST_PTR&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;E devem ser combinadas usando |&lt;br /&gt;&lt;br /&gt;Nosso c&amp;#243;digo fica da seguinte forma:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	cl_int error2 = 0, error3 = 0;
	cl_mem srcA_d = clCreateBuffer (context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float) * iNumElements,
		(&lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)srcA, &amp;amp;error);
	cl_mem srcB_d = clCreateBuffer (context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float) * iNumElements,
		(&lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)srcB, &amp;amp;error2);
	cl_mem res_d = clCreateBuffer (context, CL_MEM_WRITE_ONLY, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float) * iNumElements, NULL, &amp;amp;error3);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((error | error2 | error3) != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro alocando memoria no host&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error|error2|error3);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;&amp;quot;Criando&amp;quot; um programa e um kernel&lt;/h3&gt;
Ok, criamos os Buffers, agora precisamos &amp;quot;criar&amp;quot; um programa e compil&amp;#225;-lo. Na verdade o que precisamos &amp;#233; informar quais s&amp;#227;o nossos c&amp;#243;digos OpenCl para que possam ser compilados.&lt;br /&gt;Faremos isso usando:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_program clCreateProgramWithSource (cl_context context,
						cl_uint count,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; **strings,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *lengths,	
						cl_int *errcode_ret)
&lt;/pre&gt;&lt;/div&gt;para criar o programa, e:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_int clBuildProgram (cl_program program,
				cl_uint num_devices,
				&lt;span style="color:Blue;"&gt;const&lt;/span&gt; cl_device_id *device_list,
				&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; *options,
				&lt;span style="color:Blue;"&gt;void&lt;/span&gt; (*pfn_notify)(cl_program, &lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data),
				&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data)
&lt;/pre&gt;&lt;/div&gt;para compila-lo;&lt;br /&gt;&lt;br /&gt;Segue o c&amp;#243;digo fonte desta parte:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	&lt;span style="color:Green;"&gt;// Estas tr&amp;#234;s linhas apenas conseguem o endere&amp;#231;o do kernel&lt;/span&gt;
	size_t kernelLength;
        &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;* cPathAndName = shrFindFilePath(cSourceFile, argv[0]);
        &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;* cSourceCL = oclLoadProgSource(cPathAndName, &lt;span style="color:#A31515;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &amp;amp;kernelLength);
	cl_program program = clCreateProgramWithSource (context, 1, (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;**)&amp;amp;cSourceCL, &amp;amp;kernelLength, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando o programa&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
	error = clBuildProgram (program, 0, NULL, NULL, NULL, NULL);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro buildando o programa&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;A seguir precisamos agora criar um 'kernel object', que deve ser associado ao programa que acabamos  de criar.  Isso pode ser feito utilizando:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_kernel clCreateKernel (cl_program program,
				     &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; *kernel_name,
				     cl_int *errcode_ret)	 
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Ficando o c&amp;#243;digo da seguinte maneira:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	cl_kernel vector_add_kernel = clCreateKernel (program, &lt;span style="color:#A31515;"&gt;&amp;quot;vector_add&amp;quot;&lt;/span&gt;, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando o kernel&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Invocando o Kernel&lt;/h3&gt;Ok, j&amp;#225; criamos um contexto, descobrimos os devices, criamos um command_queue, alocamos a mem&amp;#243;ria, criamos um programa e associamos os kernels.&lt;br /&gt;Basta agora chamar os kernels para que esteja tudo conclu&amp;#237;do. Para fazer isso, devemos primeiramente empilhar os argumentos. Isso pode ser feito usando:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_int clSetKernelArg (cl_kernel kernel,
				cl_uint arg_index,
				size_t arg_size,
				&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; *arg_value)
Onde:
* _kernel_ &amp;#233; o kernel ao qual deve ser empilhado o parametro;
* _{&lt;span style="color:#A31515;"&gt;&amp;quot;arg_index&amp;quot;&lt;/span&gt;}_ &amp;#233; o &amp;#237;ndice &lt;span style="color:Blue;"&gt;do&lt;/span&gt; par&amp;#226;metro a ser empilhado (primeiro parametro, segundo parametro...);
* _{&lt;span style="color:#A31515;"&gt;&amp;quot;arg_size&amp;quot;&lt;/span&gt;}_ &amp;#233; o tamanho &lt;span style="color:Blue;"&gt;do&lt;/span&gt; parametro;
* _{&lt;span style="color:#A31515;"&gt;&amp;quot;*arg_value&amp;quot;&lt;/span&gt;}_ &amp;#233; o valor &lt;span style="color:Blue;"&gt;do&lt;/span&gt; argumento;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Nosso c&amp;#243;digo de empilhamento de parametros fica da seguinte forma:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	error = clSetKernelArg (vector_add_kernel, 0, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_mem), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;srcA_d);
	error |= clSetKernelArg (vector_add_kernel, 1, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_mem), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;srcB_d);
	error |= clSetKernelArg (vector_add_kernel, 2, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_mem), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;res_d);
	error |= clSetKernelArg (vector_add_kernel, 3, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_int), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;iNumElements);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Error empilhando os parametros&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Agora chegou o t&amp;#227;o esperado momento de chamar o kernel. Para tanto utilizaremos a seguinte fun&amp;#231;&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
       cl_int clEnqueueNDRangeKernel (cl_command_queue command_queue,
						cl_kernel kernel,
						cl_uint work_dim,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *global_work_offset,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *global_work_size,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *local_work_size,
						cl_uint num_events_in_wait_list,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; cl_event *event_wait_list,
						cl_event *&lt;span style="color:Blue;"&gt;event&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;Onde:
&lt;ul&gt;&lt;li&gt;&lt;i&gt;work_dim&lt;/i&gt; &amp;#233; o n&amp;#250;mero de dimens&amp;#245;es dos work-items (1,2 ou 3);&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*global_work_offset&lt;/i&gt; deve ser mantido NULL (pelo menos nesta vers&amp;#227;o do driver opencl da NVIDIA;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*global_work_size&lt;/i&gt; &amp;#233; um vetor que descreve as dimens&amp;#245;es dos work-items;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*local_work_size&lt;/i&gt; &amp;#233; o n&amp;#250;mero de work-items por work-group (em uma analogia a CUDA, &amp;#233; o n&amp;#250;mero de threads per block;&lt;/li&gt;
&lt;li&gt;O retorno &amp;#233; o c&amp;#243;digo de erro;&lt;/li&gt;
&lt;li&gt;os outros parametros n&amp;#227;o importam por hora;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Aqui declaramos o numero de work-items por work-group e o n&amp;#250;mero de work-items total, e em seguida chamamos o kernel;&lt;br /&gt;shrRoundUp arredonda o numero de elementos para o maior multiplo do numero de work-items por work-group;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	size_t work_groups = 256;
        size_t work_items = shrRoundUp((&lt;span style="color:Blue;"&gt;int&lt;/span&gt;)work_groups, iNumElements);

	error = clEnqueueNDRangeKernel (queue, vector_add_kernel, 1, NULL, &amp;amp;work_items, &amp;amp;work_groups, 0, NULL, NULL);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro empilhando os kernels&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Recuperando os valores e fazendo o check:&lt;/h3&gt;
Chamamos o kernel! Maraviha! N&amp;#227;o foi t&amp;#227;o dif&amp;#237;cil.&lt;br /&gt;Agora temos que conseguir de volta o resultado. Para isso, devemos enfileirar uma requisi&amp;#231;&amp;#227;o de leitura de buffer. Isso pode ser feito da seguinte maneira:&lt;br /&gt;&lt;pre&gt;	 cl_int clEnqueueReadBuffer (cl_command_queue command_queue,
					cl_mem buffer,
					cl_bool blocking_read,
					size_t offset,
					size_t cb,
					void *ptr,
					cl_uint num_events_in_wait_list,
					const cl_event *event_wait_list,
					cl_event *event)&lt;/pre&gt;&lt;br /&gt;onde:
&lt;ul&gt;&lt;li&gt;&lt;i&gt;buffer&lt;/i&gt; &amp;#233; o buffer alocado no device que queremos ler;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;blocking_read&lt;/i&gt; &amp;#233; um booleano que indica se a leitura ser&amp;#225; bloqueante ou n&amp;#227;o. Isso n&amp;#227;o &amp;#233; importante agora;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;cb&lt;/i&gt; &amp;#233; o tamanho dessa mem&amp;#243;ria;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*ptr&lt;/i&gt; &amp;#233; um ponteiro para um espa&amp;#231;o de mem&amp;#243;ria (que ja deve estar com &lt;i&gt;cb&lt;/i&gt; bytes alocados) de destino, no HOST;&lt;/li&gt;
&lt;li&gt;O retorno &amp;#233; o c&amp;#243;digo de erro;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Nosso c&amp;#243;digo fica ent&amp;#245;a da seguinte maneira:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	error = clEnqueueReadBuffer (queue, res_d, CL_TRUE, 0, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements, (&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *)res, 0, NULL, NULL);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro lendo o buffer&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Faremos agora o check com a computa&amp;#231;&amp;#227;o no host:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
       &lt;span style="color:Blue;"&gt;for&lt;/span&gt; (&lt;span style="color:Blue;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; iNumElements; ++i) {
		&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (golden[i] != res[i]) {
			cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Nao fecha a computacao&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
			exit (1);
		}
	}
	cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Passou no TESTE!!!&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;E pronto, nosso programa est&amp;#225; conclu&amp;#237;do!&lt;br /&gt;Pode parecer que &amp;#233; um esfor&amp;#231;o demasiado, mas a quest&amp;#227;o &amp;#233; que essas etapas apenas ser&amp;#227;o desenvolvidas uma vez. Todos os c&amp;#243;digos utilizar&amp;#227;o basicamente a mesma estrutura, e n&amp;#227;o acredito que leve muito tempo para alguem fazer algum &lt;i&gt;wrapper&lt;/i&gt;.&lt;br /&gt;
&lt;h3&gt;Limpeza&lt;/h3&gt;Feito o trabalho, se quisermos ser programadores respons&amp;#225;veis, devemos limpar a mem&amp;#243;ria que utilizamos. Toda inicializa&amp;#231;&amp;#227;o com &lt;i&gt;clCreate&lt;/i&gt; deve ser desalocada usando &lt;i&gt;clRelease&lt;/i&gt;&lt;br /&gt;Assim temos, para nosso exemplo:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
    clReleaseKernel(vector_add_kernel);  
    clReleaseProgram(program);
    clReleaseCommandQueue(queue);
    clReleaseContext(context);
    clReleaseMemObject(srcA_d);
    clReleaseMemObject(srcB_d);
    clReleaseMemObject(res_d);
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Chegamos assim ao fim deste tutorial.&lt;br /&gt;Muito obrigado pela aten&amp;#231;&amp;#227;o. Quaisquer d&amp;#250;vidas podem me contatar.&lt;br /&gt;Abra&amp;#231;os&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Mon, 09 Nov 2009 19:51:04 GMT</pubDate><guid isPermaLink="false">Updated Wiki: OpenCl Tutorials - 1 20091109075104P</guid></item><item><title>Updated Wiki: OpenCL Tutorials</title><link>http://hl2glsl.codeplex.com/wikipage?title=OpenCL Tutorials&amp;version=4</link><description>&lt;div class="wikidoc"&gt;Ol&amp;#225;,&lt;br /&gt;estes s&amp;#227;o os tutorials dispon&amp;#237;veis at&amp;#233; agora:
&lt;ul&gt;&lt;li&gt;&lt;a href="http://hl2glsl.codeplex.com/wikipage?title=OpenCL%20Tutorials%20-%201&amp;referringTitle=OpenCL%20Tutorials"&gt;OpenCL Tutorials - 1&lt;/a&gt; (quickstart)
&lt;ul&gt;&lt;li&gt;vers&amp;#227;o em pdf: &lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=91930';"&gt;OpenCL Tutorials1.pdf&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;At&amp;#233;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Mon, 09 Nov 2009 19:45:33 GMT</pubDate><guid isPermaLink="false">Updated Wiki: OpenCL Tutorials 20091109074533P</guid></item><item><title>Updated Wiki: OpenCL Tutorials</title><link>http://hl2glsl.codeplex.com/wikipage?title=OpenCL Tutorials&amp;version=3</link><description>&lt;div class="wikidoc"&gt;Ol&amp;#225;,&lt;br /&gt;estes s&amp;#227;o os tutorials dispon&amp;#237;veis at&amp;#233; agora:
&lt;ul&gt;&lt;li&gt;&lt;a href="http://hl2glsl.codeplex.com/wikipage?title=OpenCL%20Tutorials%20-%201&amp;referringTitle=OpenCL%20Tutorials"&gt;OpenCL Tutorials - 1&lt;/a&gt; (quickstart)
&lt;ul&gt;&lt;li&gt;vers&amp;#227;o em pdf: &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=OpenCL%20Tutorials1.pdf&amp;referringTitle=OpenCL%20Tutorials"&gt;OpenCL Tutorials1.pdf&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;At&amp;#233;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Mon, 09 Nov 2009 19:44:53 GMT</pubDate><guid isPermaLink="false">Updated Wiki: OpenCL Tutorials 20091109074453P</guid></item><item><title>Updated Wiki: OpenCl Tutorials - 1</title><link>http://hl2glsl.codeplex.com/wikipage?title=OpenCl Tutorials - 1&amp;version=31</link><description>&lt;div class="wikidoc"&gt;Ol&amp;#225; a todos,&lt;br /&gt;este &amp;#233; meu primeiro tutorial sobre OpenCL, e espero que seja &amp;#250;til.&lt;br /&gt;N&amp;#227;o falarei aqui sobre OpenCL em si, j&amp;#225; que h&amp;#225; por a&amp;#237; suficientes introdu&amp;#231;&amp;#245;es a OpenCL. Come&amp;#231;arei o tutorial falando um pouco sobre o modelo de execu&amp;#231;&amp;#227;o de OpenCL, mas ser&amp;#225; algo breve. Teremos tempo mais tarde para isso.&lt;br /&gt;Neste tutorial, o que eu gostaria de providenciar &amp;#233; um &lt;i&gt;quickstart&lt;/i&gt; para que fique mais tranquilo come&amp;#231;ar a usar e a fazer testes em OpenCL.&lt;br /&gt;&lt;br /&gt;Os c&amp;#243;digos deste tutorial encontram-se aqui:
&lt;ul&gt;&lt;li&gt;&lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=86739';"&gt;main.cpp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=86740';"&gt;vector_add.cl&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Um programa OpenCL se divide em duas partes: a execu&amp;#231;&amp;#227;o do &lt;i&gt;host&lt;/i&gt;, que &amp;#233; a execu&amp;#231;&amp;#227;o na CPU, como j&amp;#225; a conhecemos. Nesta etapa apenas s&amp;#227;o adicionadas algumas instru&amp;#231;&amp;#245;es para preparar a execu&amp;#231;&amp;#227;o do &lt;i&gt;device&lt;/i&gt;.&lt;br /&gt;A outra parte, a parte do &lt;i&gt;device&lt;/i&gt;, refere-se &amp;#224; computa&amp;#231;&amp;#227;o que ocorrer&amp;#225;, no nosso caso, na GPU. Para esta deveremos nos acostumar com alguns conceitos b&amp;#225;sicos. O primeiro deles &amp;#233; o de &lt;i&gt;kernel&lt;/i&gt;. Um &lt;i&gt;kernel&lt;/i&gt;, como j&amp;#225; foi citado no blog, &amp;#233; uma fun&amp;#231;&amp;#227;o que executa no device. Uma caracter&amp;#237;stica importante do modelo &amp;#233; que temos uma execu&amp;#231;&amp;#227;o SIMT (Single Instruction Multiple Thread), ou seja, o mesmo kernel &amp;#233; executado simultaneamente com dados diferentes.&lt;br /&gt;Aceita essa id&amp;#233;ia, passamos agora para alguns conceitos auxiliares:
&lt;ul&gt;&lt;li&gt;&lt;b&gt;work-item&lt;/b&gt;: sempre que um kernel &amp;#233; lan&amp;#231;ado, cada instancia em execu&amp;#231;&amp;#227;o desse kernel torna-se um work-item. Work-items s&amp;#227;o identificados por um &amp;#237;ndice que pode ser acessado de dentro do kernel;&lt;/li&gt;&lt;/ul&gt;
Na arquitetura NVIDIA, cada work-item &amp;#233; mapeado para uma CUDA thread;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;work-group&lt;/b&gt;: &amp;#233; como os work-items s&amp;#227;o agrupados. &amp;#201; importante ressaltar que esse agrupamento &amp;#233; muito mais importante do que pode parecer a primeira vista, dado que todos os work-items pertencentes a um work-group s&amp;#227;o executados na mesma &lt;i&gt;Compute Unit&lt;/i&gt; (que s&amp;#227;o mapeados, na arquitetura NVIDIA, para Scalar Processors (SPs)), o que lhes permite interagir entre si de forma muito mais eficiente. Work-groups s&amp;#227;o mapeados, em CUDA, para &lt;i&gt;thread blocks&lt;/i&gt;;&lt;/li&gt;&lt;/ul&gt;
Work-groups possuem, assim como os work-items, IDs &amp;#250;nicos que podem ser acessados de dentro do kernel;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;NDRange&lt;/b&gt;: um NDRange &amp;#233; um grid N-dimensional (com N = 1, 2 ou 3) de work-groups. Eles tamb&amp;#233;m s&amp;#227;o acessados por um ID;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=86520" alt="opencl-execution-model.JPG" title="opencl-execution-model.JPG" /&gt;&lt;br /&gt;Este &amp;#233; um exemplo de NDRange (retirado da especifica&amp;#231;&amp;#227;o liberada pelo Khronos Group).&lt;br /&gt;&lt;br /&gt;OK. Acho que &amp;#233; o suficiente por hoje de parafern&amp;#225;lia te&amp;#243;rica. Mais tarde teremos a oportunidade de estudar mais a fundo essas caracter&amp;#237;sticas da linguagem. Por hora &amp;#233; tudo com o qual devemos nos preocupar.&lt;br /&gt;Agora gostaria de desenvolver aqui um primeiro exemplo pr&amp;#225;tico. Trata-se de um programa muito simples, que computa a soma de dois vetores.&lt;br /&gt;Este exemplo &amp;#233; fortemente baseado no exemplo an&amp;#225;logo da NVIDIA, que vem junto com o SDK do OpenCl.&lt;br /&gt;
&lt;h3&gt;Kernel&lt;/h3&gt;Certo, vamos come&amp;#231;ar com a parte f&amp;#225;cil da hist&amp;#243;ria: programando o kernel.&lt;br /&gt;Suponhamos que estiv&amp;#233;ssemos interessados em fazer uma fun&amp;#231;&amp;#227;o comum para calcular a soma entre dois vetores. Ela seria mais ou menos assim:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void vector_add_golden (const float * const srcA,
                                     const float * const srcB,
                                     float * const golden) {
	for (int i = 0; i &amp;lt; iNumElements; i++)
		golden[i] = srcA[i] + srcB[i];
}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O que temos a&amp;#237; &amp;#233; um la&amp;#231;o que itera por todos os elementos do vetor e soma seus valores, colocando o resultado no terceiro vetor.&lt;br /&gt;Se quis&amp;#233;ssemos fazer isso em OpenCL, escrever&amp;#237;amos uma fun&amp;#231;&amp;#227;o que somasse dois vetores, escreveriamos a fun&amp;#231;&amp;#227;o que soma um elemento do vetor, e esse elemento seria o indice da instancia do kernel em execu&amp;#231;&amp;#227;o. Complicado? Vamos ver um exemplo:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
__kernel &lt;span style="color:Blue;"&gt;void&lt;/span&gt; vector_add (__global &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;float&lt;/span&gt; * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; v1,
			 __global &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;float&lt;/span&gt; * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; v2,
			 __global &lt;span style="color:Blue;"&gt;float&lt;/span&gt; * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; res,
			 __global &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;int&lt;/span&gt; n) {
	&lt;span style="color:Blue;"&gt;int&lt;/span&gt; idx = get_global_id(0);

	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (idx &amp;lt; n)
		 res[idx] = v1[idx] + v2[idx];
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Percebam que utilizamos a palavra reservada &lt;b&gt;__kernel__&lt;/b&gt; para especificar que trata-se de um kernel.&lt;br /&gt;Outro detalhe est&amp;#225; em&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	&lt;span style="color:Blue;"&gt;int&lt;/span&gt; idx = get_global_id(0);

&lt;/pre&gt;&lt;/div&gt;essa instru&amp;#231;&amp;#227;o coloca em 'idx' o ID da instancia do kernel em execu&amp;#231;&amp;#227;o.&lt;br /&gt;&lt;br /&gt;Em seguida o que fazemos &amp;#233; o seguinte: O kernel se pergunta: &amp;quot;Meu ID est&amp;#225; dentro dos limites do vetor?&amp;quot;. Caso afirmativo, ele computa a soma &lt;b&gt;desse&lt;/b&gt; elemento, e caso negativo nada &amp;#233; feito.&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;alguns detalhes adicionais: &lt;/li&gt;&lt;/ul&gt;
Esse kernel deve estar obrigat&amp;#243;riamente em um arquivo com extens&amp;#227;o &amp;quot;.cl&amp;quot;, que deve ser separado dos arquivos &amp;quot;.cpp&amp;quot; ou &amp;quot;.c&amp;quot; que contiverem c&amp;#243;digo a ser compilado.&lt;br /&gt;Nos arquivos &amp;quot;.cl&amp;quot; deve constar &lt;b&gt;apenas&lt;/b&gt; c&amp;#243;digo OpenCL, visto que o c&amp;#243;digo OpenCL &amp;#233; compilado em tempo de execu&amp;#231;&amp;#227;o e deve ser 'invocado' de algum lugar.&lt;br /&gt;
&lt;h3&gt;Inicializando...&lt;/h3&gt;Ok, alta agora apenas a prepara&amp;#231;&amp;#227;o para o lan&amp;#231;amento do kernel.&lt;br /&gt;Mas n&amp;#227;o sejamos t&amp;#227;o apressados. Vamos entrar agora na parte mais chata deste tutorial.&lt;br /&gt;OpenCL &amp;#233; uma linguagem de baixo n&amp;#237;vel, portanto nos cabe o trabalho de fazer grande parte das coisas que, por exemplo, CUDA faz por n&amp;#243;s.&lt;br /&gt;Mas vamos por partes. Precisaremos, inicialmente, dos headers necess&amp;#225;rios. Isso &amp;#233; facil:&lt;br /&gt;&lt;pre&gt;
#include &amp;lt;oclUtils.h&amp;gt;
&lt;/pre&gt;&lt;br /&gt;Este &amp;#233; um arquivo disponibilizado juntamente com os exemplos da NVIDIA, e que nos d&amp;#225; algumas fun&amp;#231;&amp;#245;es interessantes, mas que n&amp;#227;o &amp;#233; necess&amp;#225;rio.&lt;br /&gt;Ele inclui sozinho o arquivo &lt;i&gt;CL/cl.h&lt;/i&gt;, que &amp;#233;, esse sim, o verdadeiro necess&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;Faremos tamb&amp;#233;m algumas declara&amp;#231;&amp;#245;es adicionais:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
#include &amp;lt;iostream&amp;gt;

&lt;span style="color:Blue;"&gt;#define&lt;/span&gt; NUM 11444777

&lt;span style="color:Blue;"&gt;using&lt;/span&gt; &lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; std;

&lt;span style="color:Green;"&gt;/* Estes s&amp;#227;o, em ordem, o nome do arquivo em que se encontra nosso kernel,
 * o n&amp;#250;mero de elementos da computa&amp;#231;&amp;#227;o e um inteiro que ser&amp;#225; utilizado para
 * verifica&amp;#231;&amp;#227;o de erros;
 */&lt;/span&gt;
&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;* cSourceFile = &lt;span style="color:#A31515;"&gt;&amp;quot;vector_add.cl&amp;quot;&lt;/span&gt;;
cl_int iNumElements = NUM;
cl_int error = 0;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Ok, mais uma tarefa f&amp;#225;cil agora: alocar a mem&amp;#243;ria do host, inicializ&amp;#225;-la e computar no host para futura verifica&amp;#231;&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Green;"&gt;/* Aqui s&amp;#227;o alocadas as vari&amp;#225;veis que residem na CPU. S&amp;#227;o elas os dois vetores a serem somados,
	 * e os dois vetores com os resultados da computa&amp;#231;&amp;#227;o no host e no device;
	 */&lt;/span&gt;
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; srcA = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; srcB = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; golden = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; res = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	
	&lt;span style="color:Green;"&gt;/* Fazemos a devida inicializa&amp;#231;&amp;#227;o dos vetores a serem somados.
	 */&lt;/span&gt;
	&lt;span style="color:Blue;"&gt;for&lt;/span&gt; (&lt;span style="color:Blue;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; iNumElements; ++i) {
		srcA[i] = srcB[i] = i;
	}
	
	&lt;span style="color:Green;"&gt;/* Aqui fazemos o c&amp;#225;lculo da soma na CPU, para fins de verifica&amp;#231;&amp;#227;o.
	 */&lt;/span&gt;
	vector_add_golden(srcA, srcB, golden);
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Contexto e Command-queue&lt;/h3&gt;Muito bem, a esta altura j&amp;#225; estamos com tudo pronto para criar nosso contexto e nossa command-queue.&lt;br /&gt;Um contexto engloba todas as variaveis e os registradores, ou seja, o estado de uma computa&amp;#231;&amp;#227;o. A command-queue, por outro lado, &amp;#233; a fila de comandos que devem ser efetuados no programa.&lt;br /&gt;Para criar o contexto, utilizaremos a seguinte fun&amp;#231;&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_context clCreateContextFromType5 (cl_context_properties *properties,
						cl_device_type device_type,
						&lt;span style="color:Blue;"&gt;void&lt;/span&gt; (*pfn_notify)(&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; *errinfo,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; *private_info, size_t cb,
						&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data),
						&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data,
						cl_int *errcode_ret)
&lt;/pre&gt;&lt;/div&gt;Onde:
&lt;ul&gt;&lt;li&gt;&lt;i&gt;properties&lt;/i&gt; &amp;#233; um vetor de propriedades co contexto, que por hora ser&amp;#225; passado como NULL;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;cl&lt;/i&gt;device&lt;i&gt;type&lt;/i&gt; especifica o tipo do device. A tabela completa encontra-se na especifica&amp;#231;&amp;#227;o, utilizaremos CL&lt;i&gt;DEVICE&lt;/i&gt;TYPE_GPU, pois estamos criando o contexto na GPU;&lt;/li&gt;
&lt;li&gt;As proximas duas informa&amp;#231;&amp;#245;es tampouco ser&amp;#227;o importantes por hora, e ser&amp;#227;o passadas como NULL;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;errcode&lt;/i&gt;ret_ &amp;#233; o inteiro, que declaramos l&amp;#225; encima, que conter&amp;#225; o c&amp;#243;digo de um eventual erro;&lt;/li&gt;&lt;/ul&gt;
Se tudo der certo, ser&amp;#225; retornado CL_SUCCESS.&lt;br /&gt;&lt;br /&gt;Nosso c&amp;#243;digo fica ent&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        cl_context context = clCreateContextFromType (NULL, CL_DEVICE_TYPE_GPU, NULL, NULL, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando contexto&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Para criar a command-queue, precisaremos primeiramente da lista de &lt;i&gt;devices&lt;/i&gt; de nosso sistema. Para fazer isto, utilizaremos a fun&amp;#231;&amp;#227;o &lt;i&gt;clGetContextInfo&lt;/i&gt;, como pode ser visto abaixo:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Green;"&gt;// Estes s&amp;#227;o, respectivamente, o vetor de devices a ser preenchido e o tamanho em mem&amp;#243;ria desse vetor;&lt;/span&gt;
        cl_device_id *devices;
	size_t devices_size;
        &lt;span style="color:Green;"&gt;// Chamamos a fun&amp;#231;&amp;#227;o uma primeira vez, para conseguir o tamanho em mem&amp;#243;ria que deve ser alocado a devices;&lt;/span&gt;
	error = clGetContextInfo (context, CL_CONTEXT_DEVICES, 0, NULL, &amp;amp;devices_size);
        &lt;span style="color:Green;"&gt;// Alocamos o espaco necessario&lt;/span&gt;
	devices = (cl_device_id*) malloc (devices_size);
        &lt;span style="color:Green;"&gt;// E chamamos novamente a funcao para efetivamente colocar em 'devices' a informacao de todos os devices (no meu caso apenas uma GPU)&lt;/span&gt;
	error |= clGetContextInfo (context, CL_CONTEXT_DEVICES, devices_size, devices, 0);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro pegando informacoes do contexto;&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Muito bem, j&amp;#225; estamos prontos para a cria&amp;#231;&amp;#227;o da command_queue:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        cl_command_queue queue = clCreateCommandQueue (context, *devices, 0, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando command_queue&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Alocando mem&amp;#243;ria no device&lt;/h3&gt;
Ok, j&amp;#225; criamos as estruturas necess&amp;#225;rias para gerenciar a execu&amp;#231;&amp;#227;o OpenCL. Vamos agora alocar os vetores para serem somados na GPU, e em seguida invocar o kernel.&lt;br /&gt;Em OpenCl, temos que alocar um buffer, que &amp;#233; um espa&amp;#231;o de mem&amp;#243;ria a ser alocado em um contexto.&lt;br /&gt;A aloca&amp;#231;&amp;#227;o tem a seguinte assinatura:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_mem clCreateBuffer (cl_context context,
			cl_mem_flags flags,
			size_t size,
			&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *host_ptr,
			cl_int *errcode_ret)
&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;As flags podem ser:
&lt;ul&gt;&lt;li&gt;CL_MEM_READ_WRITE&lt;/li&gt;
&lt;li&gt;CL_MEM_WRITE_ONLY&lt;/li&gt;
&lt;li&gt;CL_MEM_READ_ONLY&lt;/li&gt;
&lt;li&gt;CL_MEM_USE_HOST_PTR&lt;/li&gt;
&lt;li&gt;CL_MEM_ALLOC_HOST_PTR&lt;/li&gt;
&lt;li&gt;CL_MEM_COPY_HOST_PTR&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;E devem ser combinadas usando |&lt;br /&gt;&lt;br /&gt;Nosso c&amp;#243;digo fica da seguinte forma:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	cl_int error2 = 0, error3 = 0;
	cl_mem srcA_d = clCreateBuffer (context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float) * iNumElements,
		(&lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)srcA, &amp;amp;error);
	cl_mem srcB_d = clCreateBuffer (context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float) * iNumElements,
		(&lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)srcB, &amp;amp;error2);
	cl_mem res_d = clCreateBuffer (context, CL_MEM_WRITE_ONLY, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float) * iNumElements, NULL, &amp;amp;error3);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((error | error2 | error3) != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro alocando memoria no host&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error|error2|error3);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;&amp;quot;Criando&amp;quot; um programa e um kernel&lt;/h3&gt;
Ok, criamos os Buffers, agora precisamos &amp;quot;criar&amp;quot; um programa e compil&amp;#225;-lo. Na verdade o que precisamos &amp;#233; informar quais s&amp;#227;o nossos c&amp;#243;digos OpenCl para que possam ser compilados.&lt;br /&gt;Faremos isso usando:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_program clCreateProgramWithSource (cl_context context,
						cl_uint count,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; **strings,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *lengths,	
						cl_int *errcode_ret)
&lt;/pre&gt;&lt;/div&gt;para criar o programa, e:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_int clBuildProgram (cl_program program,
				cl_uint num_devices,
				&lt;span style="color:Blue;"&gt;const&lt;/span&gt; cl_device_id *device_list,
				&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; *options,
				&lt;span style="color:Blue;"&gt;void&lt;/span&gt; (*pfn_notify)(cl_program, &lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data),
				&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data)
&lt;/pre&gt;&lt;/div&gt;para compila-lo;&lt;br /&gt;&lt;br /&gt;Segue o c&amp;#243;digo fonte desta parte:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	&lt;span style="color:Green;"&gt;// Estas tr&amp;#234;s linhas apenas conseguem o endere&amp;#231;o do kernel&lt;/span&gt;
	size_t kernelLength;
        &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;* cPathAndName = shrFindFilePath(cSourceFile, argv[0]);
        &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;* cSourceCL = oclLoadProgSource(cPathAndName, &lt;span style="color:#A31515;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &amp;amp;kernelLength);
	cl_program program = clCreateProgramWithSource (context, 1, (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;**)&amp;amp;cSourceCL, &amp;amp;kernelLength, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando o programa&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
	error = clBuildProgram (program, 0, NULL, NULL, NULL, NULL);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro buildando o programa&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;A seguir precisamos agora criar um 'kernel object', que deve ser associado ao programa que acabamos  de criar.  Isso pode ser feito utilizando:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_kernel clCreateKernel (cl_program program,
				     &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; *kernel_name,
				     cl_int *errcode_ret)	 
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Ficando o c&amp;#243;digo da seguinte maneira:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	cl_kernel vector_add_kernel = clCreateKernel (program, &lt;span style="color:#A31515;"&gt;&amp;quot;vector_add&amp;quot;&lt;/span&gt;, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando o kernel&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Invocando o Kernel&lt;/h3&gt;Ok, j&amp;#225; criamos um contexto, descobrimos os devices, criamos um command_queue, alocamos a mem&amp;#243;ria, criamos um programa e associamos os kernels.&lt;br /&gt;Basta agora chamar os kernels para que esteja tudo conclu&amp;#237;do. Para fazer isso, devemos primeiramente empilhar os argumentos. Isso pode ser feito usando:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_int clSetKernelArg (cl_kernel kernel,
				cl_uint arg_index,
				size_t arg_size,
				&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; *arg_value)
Onde:
* _kernel_ &amp;#233; o kernel ao qual deve ser empilhado o parametro;
* _{&lt;span style="color:#A31515;"&gt;&amp;quot;arg_index&amp;quot;&lt;/span&gt;}_ &amp;#233; o &amp;#237;ndice &lt;span style="color:Blue;"&gt;do&lt;/span&gt; par&amp;#226;metro a ser empilhado (primeiro parametro, segundo parametro...);
* _{&lt;span style="color:#A31515;"&gt;&amp;quot;arg_size&amp;quot;&lt;/span&gt;}_ &amp;#233; o tamanho &lt;span style="color:Blue;"&gt;do&lt;/span&gt; parametro;
* _{&lt;span style="color:#A31515;"&gt;&amp;quot;*arg_value&amp;quot;&lt;/span&gt;}_ &amp;#233; o valor &lt;span style="color:Blue;"&gt;do&lt;/span&gt; argumento;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Nosso c&amp;#243;digo de empilhamento de parametros fica da seguinte forma:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	error = clSetKernelArg (vector_add_kernel, 0, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_mem), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;srcA_d);
	error |= clSetKernelArg (vector_add_kernel, 1, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_mem), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;srcB_d);
	error |= clSetKernelArg (vector_add_kernel, 2, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_mem), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;res_d);
	error |= clSetKernelArg (vector_add_kernel, 3, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_int), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;iNumElements);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Error empilhando os parametros&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Agora chegou o t&amp;#227;o esperado momento de chamar o kernel. Para tanto utilizaremos a seguinte fun&amp;#231;&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
       cl_int clEnqueueNDRangeKernel (cl_command_queue command_queue,
						cl_kernel kernel,
						cl_uint work_dim,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *global_work_offset,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *global_work_size,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *local_work_size,
						cl_uint num_events_in_wait_list,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; cl_event *event_wait_list,
						cl_event *&lt;span style="color:Blue;"&gt;event&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;Onde:
&lt;ul&gt;&lt;li&gt;&lt;i&gt;work_dim&lt;/i&gt; &amp;#233; o n&amp;#250;mero de dimens&amp;#245;es dos work-items (1,2 ou 3);&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*global_work_offset&lt;/i&gt; deve ser mantido NULL (pelo menos nesta vers&amp;#227;o do driver opencl da NVIDIA;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*global_work_size&lt;/i&gt; &amp;#233; um vetor que descreve as dimens&amp;#245;es dos work-items;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*local_work_size&lt;/i&gt; &amp;#233; o n&amp;#250;mero de work-items por work-group (em uma analogia a CUDA, &amp;#233; o n&amp;#250;mero de threads per block;&lt;/li&gt;
&lt;li&gt;O retorno &amp;#233; o c&amp;#243;digo de erro;&lt;/li&gt;
&lt;li&gt;os outros parametros n&amp;#227;o importam por hora;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Aqui declaramos o numero de work-items por work-group e o n&amp;#250;mero de work-items total, e em seguida chamamos o kernel;&lt;br /&gt;shrRoundUp arredonda o numero de elementos para o maior multiplo do numero de work-items por work-group;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	size_t work_groups = 256;
        size_t work_items = shrRoundUp((&lt;span style="color:Blue;"&gt;int&lt;/span&gt;)work_groups, iNumElements);

	error = clEnqueueNDRangeKernel (queue, vector_add_kernel, 1, NULL, &amp;amp;work_items, &amp;amp;work_groups, 0, NULL, NULL);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro empilhando os kernels&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Recuperando os valores e fazendo o check:&lt;/h3&gt;
Chamamos o kernel! Maraviha! N&amp;#227;o foi t&amp;#227;o dif&amp;#237;cil.&lt;br /&gt;Agora temos que conseguir de volta o resultado. Para isso, devemos enfileirar uma requisi&amp;#231;&amp;#227;o de leitura de buffer. Isso pode ser feito da seguinte maneira:&lt;br /&gt;&lt;pre&gt;	 cl_int clEnqueueReadBuffer (cl_command_queue command_queue,
					cl_mem buffer,
					cl_bool blocking_read,
					size_t offset,
					size_t cb,
					void *ptr,
					cl_uint num_events_in_wait_list,
					const cl_event *event_wait_list,
					cl_event *event)&lt;/pre&gt;&lt;br /&gt;onde:
&lt;ul&gt;&lt;li&gt;&lt;i&gt;buffer&lt;/i&gt; &amp;#233; o buffer alocado no device que queremos ler;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;blocking_read&lt;/i&gt; &amp;#233; um booleano que indica se a leitura ser&amp;#225; bloqueante ou n&amp;#227;o. Isso n&amp;#227;o &amp;#233; importante agora;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;cb&lt;/i&gt; &amp;#233; o tamanho dessa mem&amp;#243;ria;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*ptr&lt;/i&gt; &amp;#233; um ponteiro para um espa&amp;#231;o de mem&amp;#243;ria (que ja deve estar com &lt;i&gt;cb&lt;/i&gt; bytes alocados) de destino, no HOST;&lt;/li&gt;
&lt;li&gt;O retorno &amp;#233; o c&amp;#243;digo de erro;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Nosso c&amp;#243;digo fica ent&amp;#245;a da seguinte maneira:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	error = clEnqueueReadBuffer (queue, res_d, CL_TRUE, 0, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements, (&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *)res, 0, NULL, NULL);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro lendo o buffer&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Faremos agora o check com a computa&amp;#231;&amp;#227;o no host:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
       &lt;span style="color:Blue;"&gt;for&lt;/span&gt; (&lt;span style="color:Blue;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; iNumElements; ++i) {
		&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (golden[i] != res[i]) {
			cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Nao fecha a computacao&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
			exit (1);
		}
	}
	cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Passou no TESTE!!!&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;E pronto, nosso programa est&amp;#225; conclu&amp;#237;do!&lt;br /&gt;Pode parecer que &amp;#233; um esfor&amp;#231;o demasiado, mas a quest&amp;#227;o &amp;#233; que essas etapas apenas ser&amp;#227;o desenvolvidas uma vez. Todos os c&amp;#243;digos utilizar&amp;#227;o basicamente a mesma estrutura, e n&amp;#227;o acredito que leve muito tempo para alguem fazer algum &lt;i&gt;wrapper&lt;/i&gt;.&lt;br /&gt;
&lt;h3&gt;Limpeza&lt;/h3&gt;Feito o trabalho, se quisermos ser programadores respons&amp;#225;veis, devemos limpar a mem&amp;#243;ria que utilizamos. Toda inicializa&amp;#231;&amp;#227;o com &lt;i&gt;clCreate&lt;/i&gt; deve ser desalocada usando &lt;i&gt;clRelease&lt;/i&gt;&lt;br /&gt;Assim temos, para nosso exemplo:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
    clReleaseKernel(vector_add_kernel);  
    clReleaseProgram(program);
    clReleaseCommandQueue(queue);
    clReleaseContext(context);
    clReleaseMemObject(srcA_d);
    clReleaseMemObject(srcB_d);
    clReleaseMemObject(res_d);
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Chegamos assim ao fim deste tutorial.&lt;br /&gt;Muito obrigado pela aten&amp;#231;&amp;#227;o. Quaisquer d&amp;#250;vidas podem me contatar.&lt;br /&gt;Abra&amp;#231;os&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Mon, 09 Nov 2009 19:43:02 GMT</pubDate><guid isPermaLink="false">Updated Wiki: OpenCl Tutorials - 1 20091109074302P</guid></item><item><title>Updated Wiki: OpenCl Tutorials - 1</title><link>http://hl2glsl.codeplex.com/wikipage?title=OpenCl Tutorials - 1&amp;version=30</link><description>&lt;div class="wikidoc"&gt;Ol&amp;#225; a todos,&lt;br /&gt;este &amp;#233; meu primeiro tutorial sobre OpenCL, e espero que seja &amp;#250;til.&lt;br /&gt;N&amp;#227;o falarei aqui sobre OpenCL em si, j&amp;#225; que h&amp;#225; por a&amp;#237; suficientes introdu&amp;#231;&amp;#245;es a OpenCL. Come&amp;#231;arei o tutorial falando um pouco sobre o modelo de execu&amp;#231;&amp;#227;o de OpenCL, mas ser&amp;#225; algo breve. Teremos tempo mais tarde para isso.&lt;br /&gt;Neste tutorial, o que eu gostaria de providenciar &amp;#233; um &lt;i&gt;quickstart&lt;/i&gt; para que fique mais tranquilo come&amp;#231;ar a usar e a fazer testes em OpenCL.&lt;br /&gt;&lt;br /&gt;Os c&amp;#243;digos deste tutorial encontram-se aqui:
&lt;ul&gt;&lt;li&gt;&lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=86739';"&gt;main.cpp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=86740';"&gt;vector_add.cl&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Um programa OpenCL se divide em duas partes: a execu&amp;#231;&amp;#227;o do &lt;i&gt;host&lt;/i&gt;, que &amp;#233; a execu&amp;#231;&amp;#227;o na CPU, como j&amp;#225; a conhecemos. Nesta etapa apenas s&amp;#227;o adicionadas algumas instru&amp;#231;&amp;#245;es para preparar a execu&amp;#231;&amp;#227;o do &lt;i&gt;device&lt;/i&gt;.&lt;br /&gt;A outra parte, a parte do &lt;i&gt;device&lt;/i&gt;, refere-se &amp;#224; computa&amp;#231;&amp;#227;o que ocorrer&amp;#225;, no nosso caso, na GPU. Para esta deveremos nos acostumar com alguns conceitos b&amp;#225;sicos. O primeiro deles &amp;#233; o de &lt;i&gt;kernel&lt;/i&gt;. Um &lt;i&gt;kernel&lt;/i&gt;, como j&amp;#225; foi citado no blog, &amp;#233; uma fun&amp;#231;&amp;#227;o que executa no device. Uma caracter&amp;#237;stica importante do modelo &amp;#233; que temos uma execu&amp;#231;&amp;#227;o SIMT (Single Instruction Multiple Thread), ou seja, o mesmo kernel &amp;#233; executado simultaneamente com dados diferentes.&lt;br /&gt;Aceita essa id&amp;#233;ia, passamos agora para alguns conceitos auxiliares:
&lt;ul&gt;&lt;li&gt;&lt;b&gt;work-item&lt;/b&gt;: sempre que um kernel &amp;#233; lan&amp;#231;ado, cada instancia em execu&amp;#231;&amp;#227;o desse kernel torna-se um work-item. Work-items s&amp;#227;o identificados por um &amp;#237;ndice que pode ser acessado de dentro do kernel;&lt;/li&gt;&lt;/ul&gt;
Na arquitetura nVidia, cada work-item &amp;#233; mapeado para uma CUDA thread;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;work-group&lt;/b&gt;: &amp;#233; como os work-items s&amp;#227;o agrupados. &amp;#201; importante ressaltar que esse agrupamento &amp;#233; muito mais importante do que pode parecer a primeira vista, dado que todos os work-items pertencentes a um work-group s&amp;#227;o executados na mesma &lt;i&gt;Compute Unit&lt;/i&gt; (que s&amp;#227;o mapeados, na arquitetura nVidia, para Scalar Processors (SPs)), o que lhes permite interagir entre si de forma muito mais eficiente. Work-groups s&amp;#227;o mapeados, em CUDA, para &lt;i&gt;thread blocks&lt;/i&gt;;&lt;/li&gt;&lt;/ul&gt;
Work-groups possuem, assim como os work-items, IDs &amp;#250;nicos que podem ser acessados de dentro do kernel;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;NDRange&lt;/b&gt;: um NDRange &amp;#233; um grid N-dimensional (com N = 1, 2 ou 3) de work-groups. Eles tamb&amp;#233;m s&amp;#227;o acessados por um ID;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=86520" alt="opencl-execution-model.JPG" title="opencl-execution-model.JPG" /&gt;&lt;br /&gt;Este &amp;#233; um exemplo de NDRange (retirado da especifica&amp;#231;&amp;#227;o liberada pelo Khronos Group).&lt;br /&gt;&lt;br /&gt;OK. Acho que &amp;#233; o suficiente por hoje de parafern&amp;#225;lia te&amp;#243;rica. Mais tarde teremos a oportunidade de estudar mais a fundo essas caracter&amp;#237;sticas da linguagem. Por hora &amp;#233; tudo com o qual devemos nos preocupar.&lt;br /&gt;Agora gostaria de desenvolver aqui um primeiro exemplo pr&amp;#225;tico. Trata-se de um programa muito simples, que computa a soma de dois vetores.&lt;br /&gt;Este exemplo &amp;#233; fortemente baseado no exemplo an&amp;#225;logo da nVidia, que vem junto com o SDK do OpenCl.&lt;br /&gt;
&lt;h3&gt;Kernel&lt;/h3&gt;Certo, vamos come&amp;#231;ar com a parte f&amp;#225;cil da hist&amp;#243;ria: programando o kernel.&lt;br /&gt;Suponhamos que estiv&amp;#233;ssemos interessados em fazer uma fun&amp;#231;&amp;#227;o comum para calcular a soma entre dois vetores. Ela seria mais ou menos assim:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void vector_add_golden (const float * const srcA,
                                     const float * const srcB,
                                     float * const golden) {
	for (int i = 0; i &amp;lt; iNumElements; i++)
		golden[i] = srcA[i] + srcB[i];
}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O que temos a&amp;#237; &amp;#233; um la&amp;#231;o que itera por todos os elementos do vetor e soma seus valores, colocando o resultado no terceiro vetor.&lt;br /&gt;Se quis&amp;#233;ssemos fazer isso em OpenCL, escrever&amp;#237;amos uma fun&amp;#231;&amp;#227;o que somasse dois vetores, escreveriamos a fun&amp;#231;&amp;#227;o que soma um elemento do vetor, e esse elemento seria o indice da instancia do kernel em execu&amp;#231;&amp;#227;o. Complicado? Vamos ver um exemplo:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
__kernel &lt;span style="color:Blue;"&gt;void&lt;/span&gt; vector_add (__global &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;float&lt;/span&gt; * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; v1,
			 __global &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;float&lt;/span&gt; * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; v2,
			 __global &lt;span style="color:Blue;"&gt;float&lt;/span&gt; * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; res,
			 __global &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;int&lt;/span&gt; n) {
	&lt;span style="color:Blue;"&gt;int&lt;/span&gt; idx = get_global_id(0);

	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (idx &amp;lt; n)
		 res[idx] = v1[idx] + v2[idx];
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Percebam que utilizamos a palavra reservada &lt;b&gt;__kernel__&lt;/b&gt; para especificar que trata-se de um kernel.&lt;br /&gt;Outro detalhe est&amp;#225; em&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	&lt;span style="color:Blue;"&gt;int&lt;/span&gt; idx = get_global_id(0);

&lt;/pre&gt;&lt;/div&gt;essa instru&amp;#231;&amp;#227;o coloca em 'idx' o ID da instancia do kernel em execu&amp;#231;&amp;#227;o.&lt;br /&gt;&lt;br /&gt;Em seguida o que fazemos &amp;#233; o seguinte: O kernel se pergunta: &amp;quot;Meu ID est&amp;#225; dentro dos limites do vetor?&amp;quot;. Caso afirmativo, ele computa a soma &lt;b&gt;desse&lt;/b&gt; elemento, e caso negativo nada &amp;#233; feito.&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;alguns detalhes adicionais: &lt;/li&gt;&lt;/ul&gt;
Esse kernel deve estar obrigat&amp;#243;riamente em um arquivo com extens&amp;#227;o &amp;quot;.cl&amp;quot;, que deve ser separado dos arquivos &amp;quot;.cpp&amp;quot; ou &amp;quot;.c&amp;quot; que contiverem c&amp;#243;digo a ser compilado.&lt;br /&gt;Nos arquivos &amp;quot;.cl&amp;quot; deve constar &lt;b&gt;apenas&lt;/b&gt; c&amp;#243;digo OpenCL, visto que o c&amp;#243;digo OpenCL &amp;#233; compilado em tempo de execu&amp;#231;&amp;#227;o e deve ser 'invocado' de algum lugar.&lt;br /&gt;
&lt;h3&gt;Inicializando...&lt;/h3&gt;Ok, alta agora apenas a prepara&amp;#231;&amp;#227;o para o lan&amp;#231;amento do kernel.&lt;br /&gt;Mas n&amp;#227;o sejamos t&amp;#227;o apressados. Vamos entrar agora na parte mais chata deste tutorial.&lt;br /&gt;OpenCL &amp;#233; uma linguagem de baixo n&amp;#237;vel, portanto nos cabe o trabalho de fazer grande parte das coisas que, por exemplo, CUDA faz por n&amp;#243;s.&lt;br /&gt;Mas vamos por partes. Precisaremos, inicialmente, dos headers necess&amp;#225;rios. Isso &amp;#233; facil:&lt;br /&gt;&lt;pre&gt;
#include &amp;lt;oclUtils.h&amp;gt;
&lt;/pre&gt;&lt;br /&gt;Este &amp;#233; um arquivo disponibilizado juntamente com os exemplos da nVidia, e que nos d&amp;#225; algumas fun&amp;#231;&amp;#245;es interessantes, mas que n&amp;#227;o &amp;#233; necess&amp;#225;rio.&lt;br /&gt;Ele inclui sozinho o arquivo &lt;i&gt;CL/cl.h&lt;/i&gt;, que &amp;#233;, esse sim, o verdadeiro necess&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;Faremos tamb&amp;#233;m algumas declara&amp;#231;&amp;#245;es adicionais:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
#include &amp;lt;iostream&amp;gt;

&lt;span style="color:Blue;"&gt;#define&lt;/span&gt; NUM 11444777

&lt;span style="color:Blue;"&gt;using&lt;/span&gt; &lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; std;

&lt;span style="color:Green;"&gt;/* Estes s&amp;#227;o, em ordem, o nome do arquivo em que se encontra nosso kernel,
 * o n&amp;#250;mero de elementos da computa&amp;#231;&amp;#227;o e um inteiro que ser&amp;#225; utilizado para
 * verifica&amp;#231;&amp;#227;o de erros;
 */&lt;/span&gt;
&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;* cSourceFile = &lt;span style="color:#A31515;"&gt;&amp;quot;vector_add.cl&amp;quot;&lt;/span&gt;;
cl_int iNumElements = NUM;
cl_int error = 0;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Ok, mais uma tarefa f&amp;#225;cil agora: alocar a mem&amp;#243;ria do host, inicializ&amp;#225;-la e computar no host para futura verifica&amp;#231;&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Green;"&gt;/* Aqui s&amp;#227;o alocadas as vari&amp;#225;veis que residem na CPU. S&amp;#227;o elas os dois vetores a serem somados,
	 * e os dois vetores com os resultados da computa&amp;#231;&amp;#227;o no host e no device;
	 */&lt;/span&gt;
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; srcA = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; srcB = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; golden = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; res = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	
	&lt;span style="color:Green;"&gt;/* Fazemos a devida inicializa&amp;#231;&amp;#227;o dos vetores a serem somados.
	 */&lt;/span&gt;
	&lt;span style="color:Blue;"&gt;for&lt;/span&gt; (&lt;span style="color:Blue;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; iNumElements; ++i) {
		srcA[i] = srcB[i] = i;
	}
	
	&lt;span style="color:Green;"&gt;/* Aqui fazemos o c&amp;#225;lculo da soma na CPU, para fins de verifica&amp;#231;&amp;#227;o.
	 */&lt;/span&gt;
	vector_add_golden(srcA, srcB, golden);
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Contexto e Command-queue&lt;/h3&gt;Muito bem, a esta altura j&amp;#225; estamos com tudo pronto para criar nosso contexto e nossa command-queue.&lt;br /&gt;Um contexto engloba todas as variaveis e os registradores, ou seja, o estado de uma computa&amp;#231;&amp;#227;o. A command-queue, por outro lado, &amp;#233; a fila de comandos que devem ser efetuados no programa.&lt;br /&gt;Para criar o contexto, utilizaremos a seguinte fun&amp;#231;&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_context clCreateContextFromType5 (cl_context_properties *properties,
						cl_device_type device_type,
						&lt;span style="color:Blue;"&gt;void&lt;/span&gt; (*pfn_notify)(&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; *errinfo,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; *private_info, size_t cb,
						&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data),
						&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data,
						cl_int *errcode_ret)
&lt;/pre&gt;&lt;/div&gt;Onde:
&lt;ul&gt;&lt;li&gt;&lt;i&gt;properties&lt;/i&gt; &amp;#233; um vetor de propriedades co contexto, que por hora ser&amp;#225; passado como NULL;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;cl&lt;/i&gt;device&lt;i&gt;type&lt;/i&gt; especifica o tipo do device. A tabela completa encontra-se na especifica&amp;#231;&amp;#227;o, utilizaremos CL&lt;i&gt;DEVICE&lt;/i&gt;TYPE_GPU, pois estamos criando o contexto na GPU;&lt;/li&gt;
&lt;li&gt;As proximas duas informa&amp;#231;&amp;#245;es tampouco ser&amp;#227;o importantes por hora, e ser&amp;#227;o passadas como NULL;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;errcode&lt;/i&gt;ret_ &amp;#233; o inteiro, que declaramos l&amp;#225; encima, que conter&amp;#225; o c&amp;#243;digo de um eventual erro;&lt;/li&gt;&lt;/ul&gt;
Se tudo der certo, ser&amp;#225; retornado CL_SUCCESS.&lt;br /&gt;&lt;br /&gt;Nosso c&amp;#243;digo fica ent&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        cl_context context = clCreateContextFromType (NULL, CL_DEVICE_TYPE_GPU, NULL, NULL, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando contexto&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Para criar a command-queue, precisaremos primeiramente da lista de &lt;i&gt;devices&lt;/i&gt; de nosso sistema. Para fazer isto, utilizaremos a fun&amp;#231;&amp;#227;o &lt;i&gt;clGetContextInfo&lt;/i&gt;, como pode ser visto abaixo:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Green;"&gt;// Estes s&amp;#227;o, respectivamente, o vetor de devices a ser preenchido e o tamanho em mem&amp;#243;ria desse vetor;&lt;/span&gt;
        cl_device_id *devices;
	size_t devices_size;
        &lt;span style="color:Green;"&gt;// Chamamos a fun&amp;#231;&amp;#227;o uma primeira vez, para conseguir o tamanho em mem&amp;#243;ria que deve ser alocado a devices;&lt;/span&gt;
	error = clGetContextInfo (context, CL_CONTEXT_DEVICES, 0, NULL, &amp;amp;devices_size);
        &lt;span style="color:Green;"&gt;// Alocamos o espaco necessario&lt;/span&gt;
	devices = (cl_device_id*) malloc (devices_size);
        &lt;span style="color:Green;"&gt;// E chamamos novamente a funcao para efetivamente colocar em 'devices' a informacao de todos os devices (no meu caso apenas uma GPU)&lt;/span&gt;
	error |= clGetContextInfo (context, CL_CONTEXT_DEVICES, devices_size, devices, 0);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro pegando informacoes do contexto;&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Muito bem, j&amp;#225; estamos prontos para a cria&amp;#231;&amp;#227;o da command_queue:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        cl_command_queue queue = clCreateCommandQueue (context, *devices, 0, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando command_queue&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Alocando mem&amp;#243;ria no device&lt;/h3&gt;
Ok, j&amp;#225; criamos as estruturas necess&amp;#225;rias para gerenciar a execu&amp;#231;&amp;#227;o OpenCL. Vamos agora alocar os vetores para serem somados na GPU, e em seguida invocar o kernel.&lt;br /&gt;Em OpenCl, temos que alocar um buffer, que &amp;#233; um espa&amp;#231;o de mem&amp;#243;ria a ser alocado em um contexto.&lt;br /&gt;A aloca&amp;#231;&amp;#227;o tem a seguinte assinatura:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_mem clCreateBuffer (cl_context context,
			cl_mem_flags flags,
			size_t size,
			&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *host_ptr,
			cl_int *errcode_ret)
&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;As flags podem ser:
&lt;ul&gt;&lt;li&gt;CL_MEM_READ_WRITE&lt;/li&gt;
&lt;li&gt;CL_MEM_WRITE_ONLY&lt;/li&gt;
&lt;li&gt;CL_MEM_READ_ONLY&lt;/li&gt;
&lt;li&gt;CL_MEM_USE_HOST_PTR&lt;/li&gt;
&lt;li&gt;CL_MEM_ALLOC_HOST_PTR&lt;/li&gt;
&lt;li&gt;CL_MEM_COPY_HOST_PTR&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;E devem ser combinadas usando |&lt;br /&gt;&lt;br /&gt;Nosso c&amp;#243;digo fica da seguinte forma:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	cl_int error2 = 0, error3 = 0;
	cl_mem srcA_d = clCreateBuffer (context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float) * iNumElements,
		(&lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)srcA, &amp;amp;error);
	cl_mem srcB_d = clCreateBuffer (context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float) * iNumElements,
		(&lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)srcB, &amp;amp;error2);
	cl_mem res_d = clCreateBuffer (context, CL_MEM_WRITE_ONLY, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float) * iNumElements, NULL, &amp;amp;error3);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((error | error2 | error3) != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro alocando memoria no host&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error|error2|error3);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;&amp;quot;Criando&amp;quot; um programa e um kernel&lt;/h3&gt;
Ok, criamos os Buffers, agora precisamos &amp;quot;criar&amp;quot; um programa e compil&amp;#225;-lo. Na verdade o que precisamos &amp;#233; informar quais s&amp;#227;o nossos c&amp;#243;digos OpenCl para que possam ser compilados.&lt;br /&gt;Faremos isso usando:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_program clCreateProgramWithSource (cl_context context,
						cl_uint count,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; **strings,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *lengths,	
						cl_int *errcode_ret)
&lt;/pre&gt;&lt;/div&gt;para criar o programa, e:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_int clBuildProgram (cl_program program,
				cl_uint num_devices,
				&lt;span style="color:Blue;"&gt;const&lt;/span&gt; cl_device_id *device_list,
				&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; *options,
				&lt;span style="color:Blue;"&gt;void&lt;/span&gt; (*pfn_notify)(cl_program, &lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data),
				&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data)
&lt;/pre&gt;&lt;/div&gt;para compila-lo;&lt;br /&gt;&lt;br /&gt;Segue o c&amp;#243;digo fonte desta parte:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	&lt;span style="color:Green;"&gt;// Estas tr&amp;#234;s linhas apenas conseguem o endere&amp;#231;o do kernel&lt;/span&gt;
	size_t kernelLength;
        &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;* cPathAndName = shrFindFilePath(cSourceFile, argv[0]);
        &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;* cSourceCL = oclLoadProgSource(cPathAndName, &lt;span style="color:#A31515;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &amp;amp;kernelLength);
	cl_program program = clCreateProgramWithSource (context, 1, (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;**)&amp;amp;cSourceCL, &amp;amp;kernelLength, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando o programa&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
	error = clBuildProgram (program, 0, NULL, NULL, NULL, NULL);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro buildando o programa&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;A seguir precisamos agora criar um 'kernel object', que deve ser associado ao programa que acabamos  de criar.  Isso pode ser feito utilizando:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_kernel clCreateKernel (cl_program program,
				     &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; *kernel_name,
				     cl_int *errcode_ret)	 
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Ficando o c&amp;#243;digo da seguinte maneira:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	cl_kernel vector_add_kernel = clCreateKernel (program, &lt;span style="color:#A31515;"&gt;&amp;quot;vector_add&amp;quot;&lt;/span&gt;, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando o kernel&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Invocando o Kernel&lt;/h3&gt;Ok, j&amp;#225; criamos um contexto, descobrimos os devices, criamos um command_queue, alocamos a mem&amp;#243;ria, criamos um programa e associamos os kernels.&lt;br /&gt;Basta agora chamar os kernels para que esteja tudo conclu&amp;#237;do. Para fazer isso, devemos primeiramente empilhar os argumentos. Isso pode ser feito usando:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_int clSetKernelArg (cl_kernel kernel,
				cl_uint arg_index,
				size_t arg_size,
				&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; *arg_value)
Onde:
* _kernel_ &amp;#233; o kernel ao qual deve ser empilhado o parametro;
* _{&lt;span style="color:#A31515;"&gt;&amp;quot;arg_index&amp;quot;&lt;/span&gt;}_ &amp;#233; o &amp;#237;ndice &lt;span style="color:Blue;"&gt;do&lt;/span&gt; par&amp;#226;metro a ser empilhado (primeiro parametro, segundo parametro...);
* _{&lt;span style="color:#A31515;"&gt;&amp;quot;arg_size&amp;quot;&lt;/span&gt;}_ &amp;#233; o tamanho &lt;span style="color:Blue;"&gt;do&lt;/span&gt; parametro;
* _{&lt;span style="color:#A31515;"&gt;&amp;quot;*arg_value&amp;quot;&lt;/span&gt;}_ &amp;#233; o valor &lt;span style="color:Blue;"&gt;do&lt;/span&gt; argumento;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Nosso c&amp;#243;digo de empilhamento de parametros fica da seguinte forma:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	error = clSetKernelArg (vector_add_kernel, 0, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_mem), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;srcA_d);
	error |= clSetKernelArg (vector_add_kernel, 1, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_mem), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;srcB_d);
	error |= clSetKernelArg (vector_add_kernel, 2, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_mem), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;res_d);
	error |= clSetKernelArg (vector_add_kernel, 3, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_int), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;iNumElements);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Error empilhando os parametros&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Agora chegou o t&amp;#227;o esperado momento de chamar o kernel. Para tanto utilizaremos a seguinte fun&amp;#231;&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
       cl_int clEnqueueNDRangeKernel (cl_command_queue command_queue,
						cl_kernel kernel,
						cl_uint work_dim,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *global_work_offset,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *global_work_size,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *local_work_size,
						cl_uint num_events_in_wait_list,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; cl_event *event_wait_list,
						cl_event *&lt;span style="color:Blue;"&gt;event&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;Onde:
&lt;ul&gt;&lt;li&gt;&lt;i&gt;work_dim&lt;/i&gt; &amp;#233; o n&amp;#250;mero de dimens&amp;#245;es dos work-items (1,2 ou 3);&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*global_work_offset&lt;/i&gt; deve ser mantido NULL (pelo menos nesta vers&amp;#227;o do driver opencl da Nvidia;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*global_work_size&lt;/i&gt; &amp;#233; um vetor que descreve as dimens&amp;#245;es dos work-items;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*local_work_size&lt;/i&gt; &amp;#233; o n&amp;#250;mero de work-items por work-group (em uma analogia a CUDA, &amp;#233; o n&amp;#250;mero de threads per block;&lt;/li&gt;
&lt;li&gt;O retorno &amp;#233; o c&amp;#243;digo de erro;&lt;/li&gt;
&lt;li&gt;os outros parametros n&amp;#227;o importam por hora;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Aqui declaramos o numero de work-items por work-group e o n&amp;#250;mero de work-items total, e em seguida chamamos o kernel;&lt;br /&gt;shrRoundUp arredonda o numero de elementos para o maior multiplo do numero de work-items por work-group;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	size_t work_groups = 256;
        size_t work_items = shrRoundUp((&lt;span style="color:Blue;"&gt;int&lt;/span&gt;)work_groups, iNumElements);

	error = clEnqueueNDRangeKernel (queue, vector_add_kernel, 1, NULL, &amp;amp;work_items, &amp;amp;work_groups, 0, NULL, NULL);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro empilhando os kernels&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Recuperando os valores e fazendo o check:&lt;/h3&gt;
Chamamos o kernel! Maraviha! N&amp;#227;o foi t&amp;#227;o dif&amp;#237;cil.&lt;br /&gt;Agora temos que conseguir de volta o resultado. Para isso, devemos enfileirar uma requisi&amp;#231;&amp;#227;o de leitura de buffer. Isso pode ser feito da seguinte maneira:&lt;br /&gt;&lt;pre&gt;	 cl_int clEnqueueReadBuffer (cl_command_queue command_queue,
					cl_mem buffer,
					cl_bool blocking_read,
					size_t offset,
					size_t cb,
					void *ptr,
					cl_uint num_events_in_wait_list,
					const cl_event *event_wait_list,
					cl_event *event)&lt;/pre&gt;&lt;br /&gt;onde:
&lt;ul&gt;&lt;li&gt;&lt;i&gt;buffer&lt;/i&gt; &amp;#233; o buffer alocado no device que queremos ler;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;blocking_read&lt;/i&gt; &amp;#233; um booleano que indica se a leitura ser&amp;#225; bloqueante ou n&amp;#227;o. Isso n&amp;#227;o &amp;#233; importante agora;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;cb&lt;/i&gt; &amp;#233; o tamanho dessa mem&amp;#243;ria;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*ptr&lt;/i&gt; &amp;#233; um ponteiro para um espa&amp;#231;o de mem&amp;#243;ria (que ja deve estar com &lt;i&gt;cb&lt;/i&gt; bytes alocados) de destino, no HOST;&lt;/li&gt;
&lt;li&gt;O retorno &amp;#233; o c&amp;#243;digo de erro;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Nosso c&amp;#243;digo fica ent&amp;#245;a da seguinte maneira:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	error = clEnqueueReadBuffer (queue, res_d, CL_TRUE, 0, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements, (&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *)res, 0, NULL, NULL);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro lendo o buffer&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Faremos agora o check com a computa&amp;#231;&amp;#227;o no host:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
       &lt;span style="color:Blue;"&gt;for&lt;/span&gt; (&lt;span style="color:Blue;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; iNumElements; ++i) {
		&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (golden[i] != res[i]) {
			cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Nao fecha a computacao&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
			exit (1);
		}
	}
	cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Passou no TESTE!!!&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;E pronto, nosso programa est&amp;#225; conclu&amp;#237;do!&lt;br /&gt;Pode parecer que &amp;#233; um esfor&amp;#231;o demasiado, mas a quest&amp;#227;o &amp;#233; que essas etapas apenas ser&amp;#227;o desenvolvidas uma vez. Todos os c&amp;#243;digos utilizar&amp;#227;o basicamente a mesma estrutura, e n&amp;#227;o acredito que leve muito tempo para alguem fazer algum &lt;i&gt;wrapper&lt;/i&gt;.&lt;br /&gt;
&lt;h3&gt;Limpeza&lt;/h3&gt;Feito o trabalho, se quisermos ser programadores respons&amp;#225;veis, devemos limpar a mem&amp;#243;ria que utilizamos. Toda inicializa&amp;#231;&amp;#227;o com &lt;i&gt;clCreate&lt;/i&gt; deve ser desalocada usando &lt;i&gt;clRelease&lt;/i&gt;&lt;br /&gt;Assim temos, para nosso exemplo:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
    clReleaseKernel(vector_add_kernel);  
    clReleaseProgram(program);
    clReleaseCommandQueue(queue);
    clReleaseContext(context);
    clReleaseMemObject(srcA_d);
    clReleaseMemObject(srcB_d);
    clReleaseMemObject(res_d);
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Chegamos assim ao fim deste tutorial.&lt;br /&gt;Muito obrigado pela aten&amp;#231;&amp;#227;o. Quaisquer d&amp;#250;vidas podem me contatar.&lt;br /&gt;Abra&amp;#231;os&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Mon, 09 Nov 2009 19:41:03 GMT</pubDate><guid isPermaLink="false">Updated Wiki: OpenCl Tutorials - 1 20091109074103P</guid></item><item><title>Updated Wiki: OpenCl Tutorials - 1</title><link>http://hl2glsl.codeplex.com/wikipage?title=OpenCl Tutorials - 1&amp;version=29</link><description>&lt;div class="wikidoc"&gt;Ol&amp;#225; a todos,&lt;br /&gt;este &amp;#233; meu primeiro tutorial sobre OpenCL, e espero que seja &amp;#250;til.&lt;br /&gt;N&amp;#227;o falarei aqui sobre OpenCL em si, j&amp;#225; que h&amp;#225; por a&amp;#237; suficientes introdu&amp;#231;&amp;#245;es a OpenCL. Come&amp;#231;arei o tutorial falando um pouco sobre o modelo de execu&amp;#231;&amp;#227;o de OpenCL, mas ser&amp;#225; algo breve. Teremos tempo mais tarde para isso.&lt;br /&gt;Neste tutorial, o que eu gostaria de providenciar &amp;#233; um &lt;i&gt;quickstart&lt;/i&gt; para que fique mais tranquilo come&amp;#231;ar a usar e a fazer testes em OpenCL.&lt;br /&gt;&lt;br /&gt;Os c&amp;#243;digos deste tutorial encontram-se aqui:
&lt;ul&gt;&lt;li&gt;&lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=86739';"&gt;main.cpp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=86740';"&gt;vector_add.cl&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Um programa OpenCL se divide em duas partes: a execu&amp;#231;&amp;#227;o do &lt;i&gt;host&lt;/i&gt;, que &amp;#233; a execu&amp;#231;&amp;#227;o na CPU, como j&amp;#225; a conhecemos. Nesta etapa apenas s&amp;#227;o adicionadas algumas instru&amp;#231;&amp;#245;es para preparar a execu&amp;#231;&amp;#227;o do &lt;i&gt;device&lt;/i&gt;.&lt;br /&gt;A outra parte, a parte do &lt;i&gt;device&lt;/i&gt;, refere-se &amp;#224; computa&amp;#231;&amp;#227;o que ocorrer&amp;#225;, no nosso caso, na GPU. Para esta deveremos nos acostumar com alguns conceitos b&amp;#225;sicos. O primeiro deles &amp;#233; o de &lt;i&gt;kernel&lt;/i&gt;. Um &lt;i&gt;kernel&lt;/i&gt;, como j&amp;#225; foi citado no blog, &amp;#233; uma fun&amp;#231;&amp;#227;o que executa no device. Uma caracter&amp;#237;stica importante do modelo &amp;#233; que temos uma execu&amp;#231;&amp;#227;o SIMT (Single Instruction Multiple Thread), ou seja, o mesmo kernel &amp;#233; executado simultaneamente com dados diferentes.&lt;br /&gt;Aceita essa id&amp;#233;ia, passamos agora para alguns conceitos auxiliares:
&lt;ul&gt;&lt;li&gt;&lt;b&gt;work-item&lt;/b&gt;: sempre que um kernel &amp;#233; lan&amp;#231;ado, cada instancia em execu&amp;#231;&amp;#227;o desse kernel torna-se um work-item. Work-items s&amp;#227;o identificados por um &amp;#237;ndice que pode ser acessado de dentro do kernel;&lt;/li&gt;&lt;/ul&gt;
Na arquitetura nVidia, cada work-item &amp;#233; mapeado para uma CUDA thread;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;work-group&lt;/b&gt;: &amp;#233; como os work-items s&amp;#227;o agrupados. &amp;#201; importante ressaltar que esse agrupamento &amp;#233; muito mais importante do que pode parecer a primeira vista, dado que todos os work-items pertencentes a um work-group s&amp;#227;o executados na mesma &lt;i&gt;Compute Unit&lt;/i&gt; (que s&amp;#227;o mapeados, na arquitetura nVidia, para Scalar Processors (SPs)), o que lhes permite interagir entre si de forma muito mais eficiente. Work-groups s&amp;#227;o mapeados, em CUDA, para &lt;i&gt;thread blocks&lt;/i&gt;;&lt;/li&gt;&lt;/ul&gt;
Work-groups possuem, assim como os work-items, IDs &amp;#250;nicos que podem ser acessados de dentro do kernel;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;NDRange&lt;/b&gt;: um NDRange &amp;#233; um grid N-dimensional (com N = 1, 2 ou 3) de work-groups. Eles tamb&amp;#233;m s&amp;#227;o acessados por um ID;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=86520" alt="opencl-execution-model.JPG" title="opencl-execution-model.JPG" /&gt;&lt;br /&gt;Este &amp;#233; um exemplo de NDRange (retirado da especifica&amp;#231;&amp;#227;o liberada pelo Khronos Group).&lt;br /&gt;&lt;br /&gt;OK. Acho que &amp;#233; o suficiente por hoje de parafern&amp;#225;lia te&amp;#243;rica. Mais tarde teremos a oportunidade de estudar mais a fundo essas caracter&amp;#237;sticas da linguagem. Por hora &amp;#233; tudo com o qual devemos nos preocupar.&lt;br /&gt;Agora gostaria de desenvolver aqui um primeiro exemplo pr&amp;#225;tico. Trata-se de um programa muito simples, que computa a soma de dois vetores.&lt;br /&gt;Este exemplo &amp;#233; fortemente baseado no exemplo an&amp;#225;logo da nVidia, que vem junto com o SDK do OpenCl.&lt;br /&gt;
&lt;h3&gt;Kernel&lt;/h3&gt;Certo, vamos come&amp;#231;ar com a parte f&amp;#225;cil da hist&amp;#243;ria: programando o kernel.&lt;br /&gt;Suponhamos que estiv&amp;#233;ssemos interessados em fazer uma fun&amp;#231;&amp;#227;o comum para calcular a soma entre dois vetores. Ela seria mais ou menos assim:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void vector_add_golden (const float * const srcA,
                                     const float * const srcB,
                                     float * const golden) {
	for (int i = 0; i &amp;lt; iNumElements; i++)
		golden[i] = srcA[i] + srcB[i];
}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O que temos a&amp;#237; &amp;#233; um la&amp;#231;o que itera por todos os elementos do vetor e soma seus valores, colocando o resultado no terceiro vetor.&lt;br /&gt;Se quis&amp;#233;ssemos fazer isso em OpenCL, escrever&amp;#237;amos uma fun&amp;#231;&amp;#227;o que somasse dois vetores, escreveriamos a fun&amp;#231;&amp;#227;o que soma um elemento do vetor, e esse elemento seria o indice da instancia do kernel em execu&amp;#231;&amp;#227;o. Complicado? Vamos ver um exemplo:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
__kernel &lt;span style="color:Blue;"&gt;void&lt;/span&gt; vector_add (__global &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;float&lt;/span&gt; * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; v1,
			 __global &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;float&lt;/span&gt; * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; v2,
			 __global &lt;span style="color:Blue;"&gt;float&lt;/span&gt; * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; res,
			 __global &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;int&lt;/span&gt; n) {
	&lt;span style="color:Blue;"&gt;int&lt;/span&gt; idx = get_global_id(0);

	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (idx &amp;lt; n)
		 res[idx] = v1[idx] + v2[idx];
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Percebam que utilizamos a palavra reservada &lt;b&gt;__kernel__&lt;/b&gt; para especificar que trata-se de um kernel :)&lt;br /&gt;Outro detalhe est&amp;#225; em&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	&lt;span style="color:Blue;"&gt;int&lt;/span&gt; idx = get_global_id(0);

&lt;/pre&gt;&lt;/div&gt;essa instru&amp;#231;&amp;#227;o coloca em 'idx' o ID da instancia do kernel em execu&amp;#231;&amp;#227;o.&lt;br /&gt;&lt;br /&gt;Em seguida o que fazemos &amp;#233; o seguinte: O kernel se pergunta: &amp;quot;Meu ID est&amp;#225; dentro dos limites do vetor?&amp;quot;. Caso afirmativo, ele computa a soma &lt;b&gt;desse&lt;/b&gt; elemento, e caso negativo nada &amp;#233; feito.&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;alguns detalhes adicionais: &lt;/li&gt;&lt;/ul&gt;
Esse kernel deve estar obrigat&amp;#243;riamente em um arquivo com extens&amp;#227;o &amp;quot;.cl&amp;quot;, que deve ser separado dos arquivos &amp;quot;.cpp&amp;quot; ou &amp;quot;.c&amp;quot; que contiverem c&amp;#243;digo a ser compilado.&lt;br /&gt;Nos arquivos &amp;quot;.cl&amp;quot; deve constar &lt;b&gt;apenas&lt;/b&gt; c&amp;#243;digo OpenCL, visto que o c&amp;#243;digo OpenCL &amp;#233; compilado em tempo de execu&amp;#231;&amp;#227;o e deve ser 'invocado' de algum lugar.&lt;br /&gt;
&lt;h3&gt;Inicializando...&lt;/h3&gt;Ok, alta agora apenas a prepara&amp;#231;&amp;#227;o para o lan&amp;#231;amento do kernel.&lt;br /&gt;Mas n&amp;#227;o sejamos t&amp;#227;o apressados. Vamos entrar agora na parte mais chata deste tutorial.&lt;br /&gt;OpenCL &amp;#233; uma linguagem de baixo n&amp;#237;vel, portanto nos cabe o trabalho de fazer grande parte das coisas que, por exemplo, CUDA faz por n&amp;#243;s.&lt;br /&gt;Mas vamos por partes. Precisaremos, inicialmente, dos headers necess&amp;#225;rios. Isso &amp;#233; facil:&lt;br /&gt;&lt;pre&gt;
#include &amp;lt;oclUtils.h&amp;gt;
&lt;/pre&gt;&lt;br /&gt;Este &amp;#233; um arquivo disponibilizado juntamente com os exemplos da nVidia, e que nos d&amp;#225; algumas fun&amp;#231;&amp;#245;es interessantes, mas que n&amp;#227;o &amp;#233; necess&amp;#225;rio.&lt;br /&gt;Ele inclui sozinho o arquivo &lt;i&gt;CL/cl.h&lt;/i&gt;, que &amp;#233;, esse sim, o verdadeiro necess&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;Faremos tamb&amp;#233;m algumas declara&amp;#231;&amp;#245;es adicionais:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
#include &amp;lt;iostream&amp;gt;

&lt;span style="color:Blue;"&gt;#define&lt;/span&gt; NUM 11444777

&lt;span style="color:Blue;"&gt;using&lt;/span&gt; &lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; std;

&lt;span style="color:Green;"&gt;/* Estes s&amp;#227;o, em ordem, o nome do arquivo em que se encontra nosso kernel,
 * o n&amp;#250;mero de elementos da computa&amp;#231;&amp;#227;o e um inteiro que ser&amp;#225; utilizado para
 * verifica&amp;#231;&amp;#227;o de erros;
 */&lt;/span&gt;
&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;* cSourceFile = &lt;span style="color:#A31515;"&gt;&amp;quot;vector_add.cl&amp;quot;&lt;/span&gt;;
cl_int iNumElements = NUM;
cl_int error = 0;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Ok, mais uma tarefa f&amp;#225;cil agora: alocar a mem&amp;#243;ria do host, inicializ&amp;#225;-la e computar no host para futura verifica&amp;#231;&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Green;"&gt;/* Aqui s&amp;#227;o alocadas as vari&amp;#225;veis que residem na CPU. S&amp;#227;o elas os dois vetores a serem somados,
	 * e os dois vetores com os resultados da computa&amp;#231;&amp;#227;o no host e no device;
	 */&lt;/span&gt;
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; srcA = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; srcB = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; golden = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; res = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	
	&lt;span style="color:Green;"&gt;/* Fazemos a devida inicializa&amp;#231;&amp;#227;o dos vetores a serem somados.
	 */&lt;/span&gt;
	&lt;span style="color:Blue;"&gt;for&lt;/span&gt; (&lt;span style="color:Blue;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; iNumElements; ++i) {
		srcA[i] = srcB[i] = i;
	}
	
	&lt;span style="color:Green;"&gt;/* Aqui fazemos o c&amp;#225;lculo da soma na CPU, para fins de verifica&amp;#231;&amp;#227;o.
	 */&lt;/span&gt;
	vector_add_golden(srcA, srcB, golden);
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Contexto e Command-queue&lt;/h3&gt;Muito bem, a esta altura j&amp;#225; estamos com tudo pronto para criar nosso contexto e nossa command-queue.&lt;br /&gt;Um contexto engloba todas as variaveis e os registradores, ou seja, o estado de uma computa&amp;#231;&amp;#227;o. A command-queue, por outro lado, &amp;#233; a fila de comandos que devem ser efetuados no programa.&lt;br /&gt;Para criar o contexto, utilizaremos a seguinte fun&amp;#231;&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_context clCreateContextFromType5 (cl_context_properties *properties,
						cl_device_type device_type,
						&lt;span style="color:Blue;"&gt;void&lt;/span&gt; (*pfn_notify)(&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; *errinfo,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; *private_info, size_t cb,
						&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data),
						&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data,
						cl_int *errcode_ret)
&lt;/pre&gt;&lt;/div&gt;Onde:
&lt;ul&gt;&lt;li&gt;&lt;i&gt;properties&lt;/i&gt; &amp;#233; um vetor de propriedades co contexto, que por hora ser&amp;#225; passado como NULL;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;cl&lt;/i&gt;device&lt;i&gt;type&lt;/i&gt; especifica o tipo do device. A tabela completa encontra-se na especifica&amp;#231;&amp;#227;o, utilizaremos CL&lt;i&gt;DEVICE&lt;/i&gt;TYPE_GPU, pois estamos criando o contexto na GPU;&lt;/li&gt;
&lt;li&gt;As proximas duas informa&amp;#231;&amp;#245;es tampouco ser&amp;#227;o importantes por hora, e ser&amp;#227;o passadas como NULL;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;errcode&lt;/i&gt;ret_ &amp;#233; o inteiro, que declaramos l&amp;#225; encima, que conter&amp;#225; o c&amp;#243;digo de um eventual erro;&lt;/li&gt;&lt;/ul&gt;
Se tudo der certo, ser&amp;#225; retornado CL_SUCCESS.&lt;br /&gt;&lt;br /&gt;Nosso c&amp;#243;digo fica ent&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        cl_context context = clCreateContextFromType (NULL, CL_DEVICE_TYPE_GPU, NULL, NULL, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando contexto&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Para criar a command-queue, precisaremos primeiramente da lista de &lt;i&gt;devices&lt;/i&gt; de nosso sistema. Para fazer isto, utilizaremos a fun&amp;#231;&amp;#227;o &lt;i&gt;clGetContextInfo&lt;/i&gt;, como pode ser visto abaixo:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Green;"&gt;// Estes s&amp;#227;o, respectivamente, o vetor de devices a ser preenchido e o tamanho em mem&amp;#243;ria desse vetor;&lt;/span&gt;
        cl_device_id *devices;
	size_t devices_size;
        &lt;span style="color:Green;"&gt;// Chamamos a fun&amp;#231;&amp;#227;o uma primeira vez, para conseguir o tamanho em mem&amp;#243;ria que deve ser alocado a devices;&lt;/span&gt;
	error = clGetContextInfo (context, CL_CONTEXT_DEVICES, 0, NULL, &amp;amp;devices_size);
        &lt;span style="color:Green;"&gt;// Alocamos o espaco necessario&lt;/span&gt;
	devices = (cl_device_id*) malloc (devices_size);
        &lt;span style="color:Green;"&gt;// E chamamos novamente a funcao para efetivamente colocar em 'devices' a informacao de todos os devices (no meu caso apenas uma GPU)&lt;/span&gt;
	error |= clGetContextInfo (context, CL_CONTEXT_DEVICES, devices_size, devices, 0);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro pegando informacoes do contexto;&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Muito bem, j&amp;#225; estamos prontos para a cria&amp;#231;&amp;#227;o da command_queue:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        cl_command_queue queue = clCreateCommandQueue (context, *devices, 0, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando command_queue&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Alocando mem&amp;#243;ria no device&lt;/h3&gt;
Ok, j&amp;#225; criamos as estruturas necess&amp;#225;rias para gerenciar a execu&amp;#231;&amp;#227;o OpenCL. Vamos agora alocar os vetores para serem somados na GPU, e em seguida invocar o kernel.&lt;br /&gt;Em OpenCl, temos que alocar um buffer, que &amp;#233; um espa&amp;#231;o de mem&amp;#243;ria a ser alocado em um contexto.&lt;br /&gt;A aloca&amp;#231;&amp;#227;o tem a seguinte assinatura:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_mem clCreateBuffer (cl_context context,
			cl_mem_flags flags,
			size_t size,
			&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *host_ptr,
			cl_int *errcode_ret)
&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;As flags podem ser:
&lt;ul&gt;&lt;li&gt;CL_MEM_READ_WRITE&lt;/li&gt;
&lt;li&gt;CL_MEM_WRITE_ONLY&lt;/li&gt;
&lt;li&gt;CL_MEM_READ_ONLY&lt;/li&gt;
&lt;li&gt;CL_MEM_USE_HOST_PTR&lt;/li&gt;
&lt;li&gt;CL_MEM_ALLOC_HOST_PTR&lt;/li&gt;
&lt;li&gt;CL_MEM_COPY_HOST_PTR&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;E devem ser combinadas usando |&lt;br /&gt;&lt;br /&gt;Nosso c&amp;#243;digo fica da seguinte forma:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	cl_int error2 = 0, error3 = 0;
	cl_mem srcA_d = clCreateBuffer (context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float) * iNumElements,
		(&lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)srcA, &amp;amp;error);
	cl_mem srcB_d = clCreateBuffer (context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float) * iNumElements,
		(&lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)srcB, &amp;amp;error2);
	cl_mem res_d = clCreateBuffer (context, CL_MEM_WRITE_ONLY, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float) * iNumElements, NULL, &amp;amp;error3);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((error | error2 | error3) != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro alocando memoria no host&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error|error2|error3);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;&amp;quot;Criando&amp;quot; um programa e um kernel&lt;/h3&gt;
Ok, criamos os Buffers, agora precisamos &amp;quot;criar&amp;quot; um programa e compil&amp;#225;-lo. Na verdade o que precisamos &amp;#233; informar quais s&amp;#227;o nossos c&amp;#243;digos OpenCl para que possam ser compilados.&lt;br /&gt;Faremos isso usando:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_program clCreateProgramWithSource (cl_context context,
						cl_uint count,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; **strings,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *lengths,	
						cl_int *errcode_ret)
&lt;/pre&gt;&lt;/div&gt;para criar o programa, e:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_int clBuildProgram (cl_program program,
				cl_uint num_devices,
				&lt;span style="color:Blue;"&gt;const&lt;/span&gt; cl_device_id *device_list,
				&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; *options,
				&lt;span style="color:Blue;"&gt;void&lt;/span&gt; (*pfn_notify)(cl_program, &lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data),
				&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data)
&lt;/pre&gt;&lt;/div&gt;para compila-lo;&lt;br /&gt;&lt;br /&gt;Segue o c&amp;#243;digo fonte desta parte:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	&lt;span style="color:Green;"&gt;// Estas tr&amp;#234;s linhas apenas conseguem o endere&amp;#231;o do kernel&lt;/span&gt;
	size_t kernelLength;
        &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;* cPathAndName = shrFindFilePath(cSourceFile, argv[0]);
        &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;* cSourceCL = oclLoadProgSource(cPathAndName, &lt;span style="color:#A31515;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &amp;amp;kernelLength);
	cl_program program = clCreateProgramWithSource (context, 1, (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;**)&amp;amp;cSourceCL, &amp;amp;kernelLength, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando o programa&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
	error = clBuildProgram (program, 0, NULL, NULL, NULL, NULL);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro buildando o programa&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;A seguir precisamos agora criar um 'kernel object', que deve ser associado ao programa que acabamos  de criar.  Isso pode ser feito utilizando:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_kernel clCreateKernel (cl_program program,
				     &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; *kernel_name,
				     cl_int *errcode_ret)	 
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Ficando o c&amp;#243;digo da seguinte maneira:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	cl_kernel vector_add_kernel = clCreateKernel (program, &lt;span style="color:#A31515;"&gt;&amp;quot;vector_add&amp;quot;&lt;/span&gt;, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando o kernel&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Invocando o Kernel&lt;/h3&gt;Ok, j&amp;#225; criamos um contexto, descobrimos os devices, criamos um command_queue, alocamos a mem&amp;#243;ria, criamos um programa e associamos os kernels.&lt;br /&gt;Basta agora chamar os kernels para que esteja tudo conclu&amp;#237;do. Para fazer isso, devemos primeiramente empilhar os argumentos. Isso pode ser feito usando:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_int clSetKernelArg (cl_kernel kernel,
				cl_uint arg_index,
				size_t arg_size,
				&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; *arg_value)
Onde:
* _kernel_ &amp;#233; o kernel ao qual deve ser empilhado o parametro;
* _{&lt;span style="color:#A31515;"&gt;&amp;quot;arg_index&amp;quot;&lt;/span&gt;}_ &amp;#233; o &amp;#237;ndice &lt;span style="color:Blue;"&gt;do&lt;/span&gt; par&amp;#226;metro a ser empilhado (primeiro parametro, segundo parametro...);
* _{&lt;span style="color:#A31515;"&gt;&amp;quot;arg_size&amp;quot;&lt;/span&gt;}_ &amp;#233; o tamanho &lt;span style="color:Blue;"&gt;do&lt;/span&gt; parametro;
* _{&lt;span style="color:#A31515;"&gt;&amp;quot;*arg_value&amp;quot;&lt;/span&gt;}_ &amp;#233; o valor &lt;span style="color:Blue;"&gt;do&lt;/span&gt; argumento;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Nosso c&amp;#243;digo de empilhamento de parametros fica da seguinte forma:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	error = clSetKernelArg (vector_add_kernel, 0, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_mem), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;srcA_d);
	error |= clSetKernelArg (vector_add_kernel, 1, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_mem), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;srcB_d);
	error |= clSetKernelArg (vector_add_kernel, 2, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_mem), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;res_d);
	error |= clSetKernelArg (vector_add_kernel, 3, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_int), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;iNumElements);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Error empilhando os parametros&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Agora chegou o t&amp;#227;o esperado momento de chamar o kernel. Para tanto utilizaremos a seguinte fun&amp;#231;&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
       cl_int clEnqueueNDRangeKernel (cl_command_queue command_queue,
						cl_kernel kernel,
						cl_uint work_dim,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *global_work_offset,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *global_work_size,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *local_work_size,
						cl_uint num_events_in_wait_list,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; cl_event *event_wait_list,
						cl_event *&lt;span style="color:Blue;"&gt;event&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;Onde:
&lt;ul&gt;&lt;li&gt;&lt;i&gt;work_dim&lt;/i&gt; &amp;#233; o n&amp;#250;mero de dimens&amp;#245;es dos work-items (1,2 ou 3);&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*global_work_offset&lt;/i&gt; deve ser mantido NULL (pelo menos nesta vers&amp;#227;o do driver opencl da Nvidia;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*global_work_size&lt;/i&gt; &amp;#233; um vetor que descreve as dimens&amp;#245;es dos work-items;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*local_work_size&lt;/i&gt; &amp;#233; o n&amp;#250;mero de work-items por work-group (em uma analogia a CUDA, &amp;#233; o n&amp;#250;mero de threads per block;&lt;/li&gt;
&lt;li&gt;O retorno &amp;#233; o c&amp;#243;digo de erro;&lt;/li&gt;
&lt;li&gt;os outros parametros n&amp;#227;o importam por hora;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Aqui declaramos o numero de work-items por work-group e o n&amp;#250;mero de work-items total, e em seguida chamamos o kernel;&lt;br /&gt;shrRoundUp arredonda o numero de elementos para o maior multiplo do numero de work-items por work-group;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	size_t work_groups = 256;
        size_t work_items = shrRoundUp((&lt;span style="color:Blue;"&gt;int&lt;/span&gt;)work_groups, iNumElements);

	error = clEnqueueNDRangeKernel (queue, vector_add_kernel, 1, NULL, &amp;amp;work_items, &amp;amp;work_groups, 0, NULL, NULL);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro empilhando os kernels&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Recuperando os valores e fazendo o check:&lt;/h3&gt;
Chamamos o kernel! Maraviha! N&amp;#227;o foi t&amp;#227;o dif&amp;#237;cil.&lt;br /&gt;Agora temos que conseguir de volta o resultado. Para isso, devemos enfileirar uma requisi&amp;#231;&amp;#227;o de leitura de buffer. Isso pode ser feito da seguinte maneira:&lt;br /&gt;&lt;pre&gt;	 cl_int clEnqueueReadBuffer (cl_command_queue command_queue,
					cl_mem buffer,
					cl_bool blocking_read,
					size_t offset,
					size_t cb,
					void *ptr,
					cl_uint num_events_in_wait_list,
					const cl_event *event_wait_list,
					cl_event *event)&lt;/pre&gt;&lt;br /&gt;onde:
&lt;ul&gt;&lt;li&gt;&lt;i&gt;buffer&lt;/i&gt; &amp;#233; o buffer alocado no device que queremos ler;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;blocking_read&lt;/i&gt; &amp;#233; um booleano que indica se a leitura ser&amp;#225; bloqueante ou n&amp;#227;o. Isso n&amp;#227;o &amp;#233; importante agora;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;cb&lt;/i&gt; &amp;#233; o tamanho dessa mem&amp;#243;ria;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*ptr&lt;/i&gt; &amp;#233; um ponteiro para um espa&amp;#231;o de mem&amp;#243;ria (que ja deve estar com &lt;i&gt;cb&lt;/i&gt; bytes alocados) de destino, no HOST;&lt;/li&gt;
&lt;li&gt;O retorno &amp;#233; o c&amp;#243;digo de erro;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Nosso c&amp;#243;digo fica ent&amp;#245;a da seguinte maneira:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	error = clEnqueueReadBuffer (queue, res_d, CL_TRUE, 0, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements, (&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *)res, 0, NULL, NULL);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro lendo o buffer&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Faremos agora o check com a computa&amp;#231;&amp;#227;o no host:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
       &lt;span style="color:Blue;"&gt;for&lt;/span&gt; (&lt;span style="color:Blue;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; iNumElements; ++i) {
		&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (golden[i] != res[i]) {
			cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Nao fecha a computacao&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
			exit (1);
		}
	}
	cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Passou no TESTE!!!&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;E pronto, nosso programa est&amp;#225; conclu&amp;#237;do!&lt;br /&gt;Pode parecer que &amp;#233; um esfor&amp;#231;o demasiado, mas a quest&amp;#227;o &amp;#233; que essas etapas apenas ser&amp;#227;o desenvolvidas uma vez. Todos os c&amp;#243;digos utilizar&amp;#227;o basicamente a mesma estrutura, e n&amp;#227;o acredito que leve muito tempo para alguem fazer algum &lt;i&gt;wrapper&lt;/i&gt;.&lt;br /&gt;
&lt;h3&gt;Limpeza&lt;/h3&gt;Feito o trabalho, se quisermos ser programadores respons&amp;#225;veis, devemos limpar a mem&amp;#243;ria que utilizamos. Toda inicializa&amp;#231;&amp;#227;o com &lt;i&gt;clCreate&lt;/i&gt; deve ser desalocada usando &lt;i&gt;clRelease&lt;/i&gt;&lt;br /&gt;Assim temos, para nosso exemplo:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
    clReleaseKernel(vector_add_kernel);  
    clReleaseProgram(program);
    clReleaseCommandQueue(queue);
    clReleaseContext(context);
    clReleaseMemObject(srcA_d);
    clReleaseMemObject(srcB_d);
    clReleaseMemObject(res_d);
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Chegamos assim ao fim deste tutorial.&lt;br /&gt;Muito obrigado pela aten&amp;#231;&amp;#227;o. Quaisquer d&amp;#250;vidas podem me contatar.&lt;br /&gt;Abra&amp;#231;os&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Mon, 09 Nov 2009 19:38:12 GMT</pubDate><guid isPermaLink="false">Updated Wiki: OpenCl Tutorials - 1 20091109073812P</guid></item><item><title>Updated Wiki: OpenCl Tutorials - 1</title><link>http://hl2glsl.codeplex.com/wikipage?title=OpenCl Tutorials - 1&amp;version=28</link><description>&lt;div class="wikidoc"&gt;Ol&amp;#225; a todos,&lt;br /&gt;este &amp;#233; meu primeiro tutorial sobre OpenCL, e espero que seja &amp;#250;til.&lt;br /&gt;N&amp;#227;o falarei aqui sobre OpenCL em si, j&amp;#225; que h&amp;#225; por ai suficientes introdu&amp;#231;&amp;#245;es a OpenCL. Come&amp;#231;arei o tutorial falando um pouco sobre o modelo de execu&amp;#231;&amp;#227;o de OpenCL, mas ser&amp;#225; algo breve. Teremos tempo mais tarde para isso.&lt;br /&gt;Neste tutorial, o que eu gostaria de providenciar &amp;#233; um &lt;i&gt;quickstart&lt;/i&gt; para que fique mais tranquilo come&amp;#231;ar a usar e a fazer testes em OpenCL.&lt;br /&gt;&lt;br /&gt;Os c&amp;#243;digos deste tutorial encontram-se aqui:
&lt;ul&gt;&lt;li&gt;&lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=86739';"&gt;main.cpp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=86740';"&gt;vector_add.cl&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Um programa OpenCL se divide em duas partes: a execu&amp;#231;&amp;#227;o do &lt;i&gt;host&lt;/i&gt;, que &amp;#233; a execu&amp;#231;&amp;#227;o na CPU, como j&amp;#225; a conhecemos. Nesta etapa apenas s&amp;#227;o adicionadas algumas instru&amp;#231;&amp;#245;es para preparar a execu&amp;#231;&amp;#227;o do &lt;i&gt;device&lt;/i&gt;.&lt;br /&gt;A outra parte, a parte do &lt;i&gt;device&lt;/i&gt;, refere-se &amp;#224; computa&amp;#231;&amp;#227;o que ocorrer&amp;#225;, no nosso caso, na GPU. Para esta deveremos nos acostumar com alguns conceitos b&amp;#225;sicos. O primeiro deles &amp;#233; o de &lt;i&gt;kernel&lt;/i&gt;. Um &lt;i&gt;kernel&lt;/i&gt;, como j&amp;#225; foi citado no blog, &amp;#233; uma fun&amp;#231;&amp;#227;o que executa no device. Uma caracter&amp;#237;stica importante do modelo &amp;#233; que temos uma execu&amp;#231;&amp;#227;o SIMT (Single Instruction Multiple Thread), ou seja, o mesmo kernel &amp;#233; executado simultaneamente com dados diferentes.&lt;br /&gt;Aceita essa id&amp;#233;ia, passamos agora para alguns conceitos auxiliares:
&lt;ul&gt;&lt;li&gt;&lt;b&gt;work-item&lt;/b&gt;: sempre que um kernel &amp;#233; lan&amp;#231;ado, cada instancia em execu&amp;#231;&amp;#227;o desse kernel torna-se um work-item. Work-items s&amp;#227;o identificados por um &amp;#237;ndice que pode ser acessado de dentro do kernel;&lt;/li&gt;&lt;/ul&gt;
Na arquitetura nVidia, cada work-item &amp;#233; mapeado para uma CUDA thread;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;work-group&lt;/b&gt;: &amp;#233; como os work-items s&amp;#227;o agrupados. &amp;#201; importante ressaltar que esse agrupamento &amp;#233; muito mais importante do que pode parecer a primeira vista, dado que todos os work-items pertencentes a um work-group s&amp;#227;o executados na mesma &lt;i&gt;Compute Unit&lt;/i&gt; (que s&amp;#227;o mapeados, na arquitetura nVidia, para Scalar Processors (SPs)), o que lhes permite interagir entre si de forma muito mais eficiente. Work-groups s&amp;#227;o mapeados, em CUDA, para &lt;i&gt;thread blocks&lt;/i&gt;;&lt;/li&gt;&lt;/ul&gt;
Work-groups possuem, assim como os work-items, IDs &amp;#250;nicos que podem ser acessados de dentro do kernel;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;NDRange&lt;/b&gt;: um NDRange &amp;#233; um grid N-dimensional (com N = 1, 2 ou 3) de work-groups. Eles tamb&amp;#233;m s&amp;#227;o acessados por um ID;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=86520" alt="opencl-execution-model.JPG" title="opencl-execution-model.JPG" /&gt;&lt;br /&gt;Este &amp;#233; um exemplo de NDRange (retirado da especifica&amp;#231;&amp;#227;o liberada pelo Khronos Group).&lt;br /&gt;&lt;br /&gt;OK. Acho que &amp;#233; o suficiente por hoje de parafern&amp;#225;lia te&amp;#243;rica. Mais tarde teremos a oportunidade de estudar mais a fundo essas caracter&amp;#237;sticas da linguagem. Por hora &amp;#233; tudo com o qual devemos nos preocupar.&lt;br /&gt;Agora gostaria de desenvolver aqui um primeiro exemplo pr&amp;#225;tico. Trata-se de um programa muito simples, que computa a soma de dois vetores.&lt;br /&gt;Este exemplo &amp;#233; fortemente baseado no exemplo an&amp;#225;logo da nVidia, que vem junto com o SDK do OpenCl.&lt;br /&gt;
&lt;h3&gt;Kernel&lt;/h3&gt;Certo, vamos come&amp;#231;ar com a parte f&amp;#225;cil da hist&amp;#243;ria: programando o kernel.&lt;br /&gt;Suponhamos que estiv&amp;#233;ssemos interessados em fazer uma fun&amp;#231;&amp;#227;o comum para calcular a soma entre dois vetores. Ela seria mais ou menos assim:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void vector_add_golden (const float * const srcA,
                                     const float * const srcB,
                                     float * const golden) {
	for (int i = 0; i &amp;lt; iNumElements; i++)
		golden[i] = srcA[i] + srcB[i];
}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O que temos a&amp;#237; &amp;#233; um la&amp;#231;o que itera por todos os elementos do vetor e soma seus valores, colocando o resultado no terceiro vetor.&lt;br /&gt;Se quis&amp;#233;ssemos fazer isso em OpenCL, escrever&amp;#237;amos uma fun&amp;#231;&amp;#227;o que somasse dois vetores, escreveriamos a fun&amp;#231;&amp;#227;o que soma um elemento do vetor, e esse elemento seria o indice da instancia do kernel em execu&amp;#231;&amp;#227;o. Complicado? Vamos ver um exemplo:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
__kernel &lt;span style="color:Blue;"&gt;void&lt;/span&gt; vector_add (__global &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;float&lt;/span&gt; * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; v1,
			 __global &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;float&lt;/span&gt; * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; v2,
			 __global &lt;span style="color:Blue;"&gt;float&lt;/span&gt; * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; res,
			 __global &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;int&lt;/span&gt; n) {
	&lt;span style="color:Blue;"&gt;int&lt;/span&gt; idx = get_global_id(0);

	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (idx &amp;lt; n)
		 res[idx] = v1[idx] + v2[idx];
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Percebam que utilizamos a palavra reservada &lt;b&gt;__kernel__&lt;/b&gt; para especificar que trata-se de um kernel :)&lt;br /&gt;Outro detalhe est&amp;#225; em&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	&lt;span style="color:Blue;"&gt;int&lt;/span&gt; idx = get_global_id(0);

&lt;/pre&gt;&lt;/div&gt;essa instru&amp;#231;&amp;#227;o coloca em 'idx' o ID da instancia do kernel em execu&amp;#231;&amp;#227;o.&lt;br /&gt;&lt;br /&gt;Em seguida o que fazemos &amp;#233; o seguinte: O kernel se pergunta: &amp;quot;Meu ID est&amp;#225; dentro dos limites do vetor?&amp;quot;. Caso afirmativo, ele computa a soma &lt;b&gt;desse&lt;/b&gt; elemento, e caso negativo nada &amp;#233; feito.&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;alguns detalhes adicionais: &lt;/li&gt;&lt;/ul&gt;
Esse kernel deve estar obrigat&amp;#243;riamente em um arquivo com extens&amp;#227;o &amp;quot;.cl&amp;quot;, que deve ser separado dos arquivos &amp;quot;.cpp&amp;quot; ou &amp;quot;.c&amp;quot; que contiverem c&amp;#243;digo a ser compilado.&lt;br /&gt;Nos arquivos &amp;quot;.cl&amp;quot; deve constar &lt;b&gt;apenas&lt;/b&gt; c&amp;#243;digo OpenCL, visto que o c&amp;#243;digo OpenCL &amp;#233; compilado em tempo de execu&amp;#231;&amp;#227;o e deve ser 'invocado' de algum lugar.&lt;br /&gt;
&lt;h3&gt;Inicializando...&lt;/h3&gt;Ok, alta agora apenas a prepara&amp;#231;&amp;#227;o para o lan&amp;#231;amento do kernel.&lt;br /&gt;Mas n&amp;#227;o sejamos t&amp;#227;o apressados. Vamos entrar agora na parte mais chata deste tutorial.&lt;br /&gt;OpenCL &amp;#233; uma linguagem de baixo n&amp;#237;vel, portanto nos cabe o trabalho de fazer grande parte das coisas que, por exemplo, CUDA faz por n&amp;#243;s.&lt;br /&gt;Mas vamos por partes. Precisaremos, inicialmente, dos headers necess&amp;#225;rios. Isso &amp;#233; facil:&lt;br /&gt;&lt;pre&gt;
#include &amp;lt;oclUtils.h&amp;gt;
&lt;/pre&gt;&lt;br /&gt;Este &amp;#233; um arquivo disponibilizado juntamente com os exemplos da nVidia, e que nos d&amp;#225; algumas fun&amp;#231;&amp;#245;es interessantes, mas que n&amp;#227;o &amp;#233; necess&amp;#225;rio.&lt;br /&gt;Ele inclui sozinho o arquivo &lt;i&gt;CL/cl.h&lt;/i&gt;, que &amp;#233;, esse sim, o verdadeiro necess&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;Faremos tamb&amp;#233;m algumas declara&amp;#231;&amp;#245;es adicionais:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
#include &amp;lt;iostream&amp;gt;

&lt;span style="color:Blue;"&gt;#define&lt;/span&gt; NUM 11444777

&lt;span style="color:Blue;"&gt;using&lt;/span&gt; &lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; std;

&lt;span style="color:Green;"&gt;/* Estes s&amp;#227;o, em ordem, o nome do arquivo em que se encontra nosso kernel,
 * o n&amp;#250;mero de elementos da computa&amp;#231;&amp;#227;o e um inteiro que ser&amp;#225; utilizado para
 * verifica&amp;#231;&amp;#227;o de erros;
 */&lt;/span&gt;
&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;* cSourceFile = &lt;span style="color:#A31515;"&gt;&amp;quot;vector_add.cl&amp;quot;&lt;/span&gt;;
cl_int iNumElements = NUM;
cl_int error = 0;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Ok, mais uma tarefa f&amp;#225;cil agora: alocar a mem&amp;#243;ria do host, inicializ&amp;#225;-la e computar no host para futura verifica&amp;#231;&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Green;"&gt;/* Aqui s&amp;#227;o alocadas as vari&amp;#225;veis que residem na CPU. S&amp;#227;o elas os dois vetores a serem somados,
	 * e os dois vetores com os resultados da computa&amp;#231;&amp;#227;o no host e no device;
	 */&lt;/span&gt;
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; srcA = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; srcB = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; golden = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	cl_float * &lt;span style="color:Blue;"&gt;const&lt;/span&gt; res = (cl_float*) malloc(&lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements);
	
	&lt;span style="color:Green;"&gt;/* Fazemos a devida inicializa&amp;#231;&amp;#227;o dos vetores a serem somados.
	 */&lt;/span&gt;
	&lt;span style="color:Blue;"&gt;for&lt;/span&gt; (&lt;span style="color:Blue;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; iNumElements; ++i) {
		srcA[i] = srcB[i] = i;
	}
	
	&lt;span style="color:Green;"&gt;/* Aqui fazemos o c&amp;#225;lculo da soma na CPU, para fins de verifica&amp;#231;&amp;#227;o.
	 */&lt;/span&gt;
	vector_add_golden(srcA, srcB, golden);
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Contexto e Command-queue&lt;/h3&gt;Muito bem, a esta altura j&amp;#225; estamos com tudo pronto para criar nosso contexto e nossa command-queue.&lt;br /&gt;Um contexto engloba todas as variaveis e os registradores, ou seja, o estado de uma computa&amp;#231;&amp;#227;o. A command-queue, por outro lado, &amp;#233; a fila de comandos que devem ser efetuados no programa.&lt;br /&gt;Para criar o contexto, utilizaremos a seguinte fun&amp;#231;&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_context clCreateContextFromType5 (cl_context_properties *properties,
						cl_device_type device_type,
						&lt;span style="color:Blue;"&gt;void&lt;/span&gt; (*pfn_notify)(&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; *errinfo,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; *private_info, size_t cb,
						&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data),
						&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data,
						cl_int *errcode_ret)
&lt;/pre&gt;&lt;/div&gt;Onde:
&lt;ul&gt;&lt;li&gt;&lt;i&gt;properties&lt;/i&gt; &amp;#233; um vetor de propriedades co contexto, que por hora ser&amp;#225; passado como NULL;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;cl&lt;/i&gt;device&lt;i&gt;type&lt;/i&gt; especifica o tipo do device. A tabela completa encontra-se na especifica&amp;#231;&amp;#227;o, utilizaremos CL&lt;i&gt;DEVICE&lt;/i&gt;TYPE_GPU, pois estamos criando o contexto na GPU;&lt;/li&gt;
&lt;li&gt;As proximas duas informa&amp;#231;&amp;#245;es tampouco ser&amp;#227;o importantes por hora, e ser&amp;#227;o passadas como NULL;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;errcode&lt;/i&gt;ret_ &amp;#233; o inteiro, que declaramos l&amp;#225; encima, que conter&amp;#225; o c&amp;#243;digo de um eventual erro;&lt;/li&gt;&lt;/ul&gt;
Se tudo der certo, ser&amp;#225; retornado CL_SUCCESS.&lt;br /&gt;&lt;br /&gt;Nosso c&amp;#243;digo fica ent&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        cl_context context = clCreateContextFromType (NULL, CL_DEVICE_TYPE_GPU, NULL, NULL, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando contexto&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Para criar a command-queue, precisaremos primeiramente da lista de &lt;i&gt;devices&lt;/i&gt; de nosso sistema. Para fazer isto, utilizaremos a fun&amp;#231;&amp;#227;o &lt;i&gt;clGetContextInfo&lt;/i&gt;, como pode ser visto abaixo:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Green;"&gt;// Estes s&amp;#227;o, respectivamente, o vetor de devices a ser preenchido e o tamanho em mem&amp;#243;ria desse vetor;&lt;/span&gt;
        cl_device_id *devices;
	size_t devices_size;
        &lt;span style="color:Green;"&gt;// Chamamos a fun&amp;#231;&amp;#227;o uma primeira vez, para conseguir o tamanho em mem&amp;#243;ria que deve ser alocado a devices;&lt;/span&gt;
	error = clGetContextInfo (context, CL_CONTEXT_DEVICES, 0, NULL, &amp;amp;devices_size);
        &lt;span style="color:Green;"&gt;// Alocamos o espaco necessario&lt;/span&gt;
	devices = (cl_device_id*) malloc (devices_size);
        &lt;span style="color:Green;"&gt;// E chamamos novamente a funcao para efetivamente colocar em 'devices' a informacao de todos os devices (no meu caso apenas uma GPU)&lt;/span&gt;
	error |= clGetContextInfo (context, CL_CONTEXT_DEVICES, devices_size, devices, 0);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro pegando informacoes do contexto;&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Muito bem, j&amp;#225; estamos prontos para a cria&amp;#231;&amp;#227;o da command_queue:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        cl_command_queue queue = clCreateCommandQueue (context, *devices, 0, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando command_queue&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Alocando mem&amp;#243;ria no device&lt;/h3&gt;
Ok, j&amp;#225; criamos as estruturas necess&amp;#225;rias para gerenciar a execu&amp;#231;&amp;#227;o OpenCL. Vamos agora alocar os vetores para serem somados na GPU, e em seguida invocar o kernel.&lt;br /&gt;Em OpenCl, temos que alocar um buffer, que &amp;#233; um espa&amp;#231;o de mem&amp;#243;ria a ser alocado em um contexto.&lt;br /&gt;A aloca&amp;#231;&amp;#227;o tem a seguinte assinatura:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_mem clCreateBuffer (cl_context context,
			cl_mem_flags flags,
			size_t size,
			&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *host_ptr,
			cl_int *errcode_ret)
&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;As flags podem ser:
&lt;ul&gt;&lt;li&gt;CL_MEM_READ_WRITE&lt;/li&gt;
&lt;li&gt;CL_MEM_WRITE_ONLY&lt;/li&gt;
&lt;li&gt;CL_MEM_READ_ONLY&lt;/li&gt;
&lt;li&gt;CL_MEM_USE_HOST_PTR&lt;/li&gt;
&lt;li&gt;CL_MEM_ALLOC_HOST_PTR&lt;/li&gt;
&lt;li&gt;CL_MEM_COPY_HOST_PTR&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;E devem ser combinadas usando |&lt;br /&gt;&lt;br /&gt;Nosso c&amp;#243;digo fica da seguinte forma:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	cl_int error2 = 0, error3 = 0;
	cl_mem srcA_d = clCreateBuffer (context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float) * iNumElements,
		(&lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)srcA, &amp;amp;error);
	cl_mem srcB_d = clCreateBuffer (context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float) * iNumElements,
		(&lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)srcB, &amp;amp;error2);
	cl_mem res_d = clCreateBuffer (context, CL_MEM_WRITE_ONLY, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float) * iNumElements, NULL, &amp;amp;error3);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((error | error2 | error3) != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro alocando memoria no host&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error|error2|error3);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;&amp;quot;Criando&amp;quot; um programa e um kernel&lt;/h3&gt;
Ok, criamos os Buffers, agora precisamos &amp;quot;criar&amp;quot; um programa e compil&amp;#225;-lo. Na verdade o que precisamos &amp;#233; informar quais s&amp;#227;o nossos c&amp;#243;digos OpenCl para que possam ser compilados.&lt;br /&gt;Faremos isso usando:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_program clCreateProgramWithSource (cl_context context,
						cl_uint count,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; **strings,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *lengths,	
						cl_int *errcode_ret)
&lt;/pre&gt;&lt;/div&gt;para criar o programa, e:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_int clBuildProgram (cl_program program,
				cl_uint num_devices,
				&lt;span style="color:Blue;"&gt;const&lt;/span&gt; cl_device_id *device_list,
				&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; *options,
				&lt;span style="color:Blue;"&gt;void&lt;/span&gt; (*pfn_notify)(cl_program, &lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data),
				&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *user_data)
&lt;/pre&gt;&lt;/div&gt;para compila-lo;&lt;br /&gt;&lt;br /&gt;Segue o c&amp;#243;digo fonte desta parte:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	&lt;span style="color:Green;"&gt;// Estas tr&amp;#234;s linhas apenas conseguem o endere&amp;#231;o do kernel&lt;/span&gt;
	size_t kernelLength;
        &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;* cPathAndName = shrFindFilePath(cSourceFile, argv[0]);
        &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;* cSourceCL = oclLoadProgSource(cPathAndName, &lt;span style="color:#A31515;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &amp;amp;kernelLength);
	cl_program program = clCreateProgramWithSource (context, 1, (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt;**)&amp;amp;cSourceCL, &amp;amp;kernelLength, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando o programa&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
	error = clBuildProgram (program, 0, NULL, NULL, NULL, NULL);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro buildando o programa&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;A seguir precisamos agora criar um 'kernel object', que deve ser associado ao programa que acabamos  de criar.  Isso pode ser feito utilizando:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_kernel clCreateKernel (cl_program program,
				     &lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;char&lt;/span&gt; *kernel_name,
				     cl_int *errcode_ret)	 
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Ficando o c&amp;#243;digo da seguinte maneira:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	cl_kernel vector_add_kernel = clCreateKernel (program, &lt;span style="color:#A31515;"&gt;&amp;quot;vector_add&amp;quot;&lt;/span&gt;, &amp;amp;error);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro criando o kernel&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Invocando o Kernel&lt;/h3&gt;Ok, j&amp;#225; criamos um contexto, descobrimos os devices, criamos um command_queue, alocamos a mem&amp;#243;ria, criamos um programa e associamos os kernels.&lt;br /&gt;Basta agora chamar os kernels para que esteja tudo conclu&amp;#237;do. Para fazer isso, devemos primeiramente empilhar os argumentos. Isso pode ser feito usando:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	 cl_int clSetKernelArg (cl_kernel kernel,
				cl_uint arg_index,
				size_t arg_size,
				&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; *arg_value)
Onde:
* _kernel_ &amp;#233; o kernel ao qual deve ser empilhado o parametro;
* _{&lt;span style="color:#A31515;"&gt;&amp;quot;arg_index&amp;quot;&lt;/span&gt;}_ &amp;#233; o &amp;#237;ndice &lt;span style="color:Blue;"&gt;do&lt;/span&gt; par&amp;#226;metro a ser empilhado (primeiro parametro, segundo parametro...);
* _{&lt;span style="color:#A31515;"&gt;&amp;quot;arg_size&amp;quot;&lt;/span&gt;}_ &amp;#233; o tamanho &lt;span style="color:Blue;"&gt;do&lt;/span&gt; parametro;
* _{&lt;span style="color:#A31515;"&gt;&amp;quot;*arg_value&amp;quot;&lt;/span&gt;}_ &amp;#233; o valor &lt;span style="color:Blue;"&gt;do&lt;/span&gt; argumento;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Nosso c&amp;#243;digo de empilhamento de parametros fica da seguinte forma:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	error = clSetKernelArg (vector_add_kernel, 0, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_mem), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;srcA_d);
	error |= clSetKernelArg (vector_add_kernel, 1, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_mem), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;srcB_d);
	error |= clSetKernelArg (vector_add_kernel, 2, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_mem), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;res_d);
	error |= clSetKernelArg (vector_add_kernel, 3, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_int), (&lt;span style="color:Blue;"&gt;const&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt;*)&amp;amp;iNumElements);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Error empilhando os parametros&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Agora chegou o t&amp;#227;o esperado momento de chamar o kernel. Para tanto utilizaremos a seguinte fun&amp;#231;&amp;#227;o:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
       cl_int clEnqueueNDRangeKernel (cl_command_queue command_queue,
						cl_kernel kernel,
						cl_uint work_dim,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *global_work_offset,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *global_work_size,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; size_t *local_work_size,
						cl_uint num_events_in_wait_list,
						&lt;span style="color:Blue;"&gt;const&lt;/span&gt; cl_event *event_wait_list,
						cl_event *&lt;span style="color:Blue;"&gt;event&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;Onde:
&lt;ul&gt;&lt;li&gt;&lt;i&gt;work_dim&lt;/i&gt; &amp;#233; o n&amp;#250;mero de dimens&amp;#245;es dos work-items (1,2 ou 3);&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*global_work_offset&lt;/i&gt; deve ser mantido NULL (pelo menos nesta vers&amp;#227;o do driver opencl da Nvidia;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*global_work_size&lt;/i&gt; &amp;#233; um vetor que descreve as dimens&amp;#245;es dos work-items;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*local_work_size&lt;/i&gt; &amp;#233; o n&amp;#250;mero de work-items por work-group (em uma analogia a CUDA, &amp;#233; o n&amp;#250;mero de threads per block;&lt;/li&gt;
&lt;li&gt;O retorno &amp;#233; o c&amp;#243;digo de erro;&lt;/li&gt;
&lt;li&gt;os outros parametros n&amp;#227;o importam por hora;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Aqui declaramos o numero de work-items por work-group e o n&amp;#250;mero de work-items total, e em seguida chamamos o kernel;&lt;br /&gt;shrRoundUp arredonda o numero de elementos para o maior multiplo do numero de work-items por work-group;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	size_t work_groups = 256;
        size_t work_items = shrRoundUp((&lt;span style="color:Blue;"&gt;int&lt;/span&gt;)work_groups, iNumElements);

	error = clEnqueueNDRangeKernel (queue, vector_add_kernel, 1, NULL, &amp;amp;work_items, &amp;amp;work_groups, 0, NULL, NULL);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro empilhando os kernels&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Recuperando os valores e fazendo o check:&lt;/h3&gt;
Chamamos o kernel! Maraviha! N&amp;#227;o foi t&amp;#227;o dif&amp;#237;cil.&lt;br /&gt;Agora temos que conseguir de volta o resultado. Para isso, devemos enfileirar uma requisi&amp;#231;&amp;#227;o de leitura de buffer. Isso pode ser feito da seguinte maneira:&lt;br /&gt;&lt;pre&gt;	 cl_int clEnqueueReadBuffer (cl_command_queue command_queue,
					cl_mem buffer,
					cl_bool blocking_read,
					size_t offset,
					size_t cb,
					void *ptr,
					cl_uint num_events_in_wait_list,
					const cl_event *event_wait_list,
					cl_event *event)&lt;/pre&gt;&lt;br /&gt;onde:
&lt;ul&gt;&lt;li&gt;&lt;i&gt;buffer&lt;/i&gt; &amp;#233; o buffer alocado no device que queremos ler;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;blocking_read&lt;/i&gt; &amp;#233; um booleano que indica se a leitura ser&amp;#225; bloqueante ou n&amp;#227;o. Isso n&amp;#227;o &amp;#233; importante agora;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;cb&lt;/i&gt; &amp;#233; o tamanho dessa mem&amp;#243;ria;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;*ptr&lt;/i&gt; &amp;#233; um ponteiro para um espa&amp;#231;o de mem&amp;#243;ria (que ja deve estar com &lt;i&gt;cb&lt;/i&gt; bytes alocados) de destino, no HOST;&lt;/li&gt;
&lt;li&gt;O retorno &amp;#233; o c&amp;#243;digo de erro;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Nosso c&amp;#243;digo fica ent&amp;#245;a da seguinte maneira:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
	error = clEnqueueReadBuffer (queue, res_d, CL_TRUE, 0, &lt;span style="color:Blue;"&gt;sizeof&lt;/span&gt;(cl_float)*iNumElements, (&lt;span style="color:Blue;"&gt;void&lt;/span&gt; *)res, 0, NULL, NULL);
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (error != CL_SUCCESS) {
		cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Erro lendo o buffer&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
		exit (error);
	}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Faremos agora o check com a computa&amp;#231;&amp;#227;o no host:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
       &lt;span style="color:Blue;"&gt;for&lt;/span&gt; (&lt;span style="color:Blue;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; iNumElements; ++i) {
		&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (golden[i] != res[i]) {
			cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Nao fecha a computacao&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
			exit (1);
		}
	}
	cout &amp;lt;&amp;lt; &lt;span style="color:#A31515;"&gt;&amp;quot;Passou no TESTE!!!&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; endl;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;E pronto, nosso programa est&amp;#225; conclu&amp;#237;do!&lt;br /&gt;Pode parecer que &amp;#233; um esfor&amp;#231;o demasiado, mas a quest&amp;#227;o &amp;#233; que essas etapas apenas ser&amp;#227;o desenvolvidas uma vez. Todos os c&amp;#243;digos utilizar&amp;#227;o basicamente a mesma estrutura, e n&amp;#227;o acredito que leve muito tempo para alguem fazer algum &lt;i&gt;wrapper&lt;/i&gt;.&lt;br /&gt;
&lt;h3&gt;Limpeza&lt;/h3&gt;Feito o trabalho, se quisermos ser programadores respons&amp;#225;veis, devemos limpar a mem&amp;#243;ria que utilizamos. Toda inicializa&amp;#231;&amp;#227;o com &lt;i&gt;clCreate&lt;/i&gt; deve ser desalocada usando &lt;i&gt;clRelease&lt;/i&gt;&lt;br /&gt;Assim temos, para nosso exemplo:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
    clReleaseKernel(vector_add_kernel);  
    clReleaseProgram(program);
    clReleaseCommandQueue(queue);
    clReleaseContext(context);
    clReleaseMemObject(srcA_d);
    clReleaseMemObject(srcB_d);
    clReleaseMemObject(res_d);
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Chegamos assim ao fim deste tutorial.&lt;br /&gt;Muito obrigado pela aten&amp;#231;&amp;#227;o. Quaisquer d&amp;#250;vidas podem me contatar.&lt;br /&gt;Abra&amp;#231;os&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Mon, 09 Nov 2009 19:36:44 GMT</pubDate><guid isPermaLink="false">Updated Wiki: OpenCl Tutorials - 1 20091109073644P</guid></item><item><title>Updated Wiki: Blog</title><link>http://hl2glsl.codeplex.com/wikipage?title=Blog&amp;version=64</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Blog do Projeto&lt;/h1&gt;
Unfortunately this page exists only in portuguese. &lt;br /&gt;
&lt;h2&gt;03/11/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estive bastante envolvido com as tarefas da faculdade nos &amp;#250;ltimos dias, assim que n&amp;#227;o tenho tido muito tempo de postar aqui os resultados do meu trabalho.&lt;br /&gt;Encontrei um material muito bom sobre OpenCl aqui: &lt;a href="http://www.macresearch.org/opencl" class="externalLink"&gt;http://www.macresearch.org/opencl&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. Nelas s&amp;#227;o apresentados desde quest&amp;#245;es gerais sobre opencl at&amp;#233; otimiza&amp;#231;&amp;#245;es diversas. Vale a pena conferir.&lt;br /&gt;At&amp;#233;,&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;05/10/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;gostaria de fazer aqui um pequeno post apenas para comentar sobre um benchmark que foi feito pela SiSoftware (os respons&amp;#225;veis pelo famoso Sandra).&lt;br /&gt;O benchmark levou em considera&amp;#231;&amp;#227;o as vers&amp;#245;es 2.2 e 2.3 do driver da NVidia, comparando CUDA e Opencl. Os resultados completos podem ser conferidos aqui: &lt;a href="http://sisoftware.co.uk/index.html?dir=qa&amp;amp;location=gpu_opencl&amp;amp;langx=en&amp;amp;a=" class="externalLink"&gt;http://sisoftware.co.uk/index.html?dir=qa&amp;amp;location=gpu_opencl&amp;amp;langx=en&amp;amp;a=&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;A id&amp;#233;ia central &amp;#233; que o OpenCl est&amp;#225; praticamente &amp;#224; altura do CUDA (tendo em vista os testes desse benchmark) em termos de desempenho, o que responde a uma grande cr&amp;#237;tica ao OpenCL.&lt;br /&gt;&lt;br /&gt;Att,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;02/10/09&lt;/h2&gt;Bom dia,&lt;br /&gt;estou postando aqui hoje meu primeiro tutorial sobre OpenCL. Esse primeiro tutorial pretende ser uma inicia&amp;#231;&amp;#227;o, um hello world detalhado de como funciona uma aplica&amp;#231;&amp;#227;o OpenCl.&lt;br /&gt;Futuros tutoriais aprofundar-se-&amp;#227;o em outros temas;&lt;br /&gt;O tutorial pode ser encontrado aqui: &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=OpenCl%20Tutorials%20-%201&amp;referringTitle=Blog"&gt;OpenCl Tutorials - 1&lt;/a&gt;;&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;30/09/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;queria avisar que a nvidia liberou para a comunidade em geral o driver da vers&amp;#227;o 1.0 do OpenCL nesta segunda feira.&lt;br /&gt;A p&amp;#225;gina com informa&amp;#231;&amp;#245;es para download tanto de windows, linux e mac pode ser encontrada aqui: &lt;a href="http://www.nvidia.com/object/cuda_opencl.html" class="externalLink"&gt;http://www.nvidia.com/object/cuda_opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/09/09&lt;/h2&gt;Bom dia,&lt;br /&gt;Nessa &amp;#250;ltima semana fiz uma pequena apresenta&amp;#231;&amp;#227;o sobre o projeto, apresentando todas as suas fases. Disponibilizo aqui apresenta&amp;#231;&amp;#227;o com &amp;#225;udio &lt;a href="http://www.inf.ufrgs.br/~lpchatain/apresentacao_chatain.pptx" class="externalLink"&gt;http://www.inf.ufrgs.br/~lpchatain/apresentacao_chatain.pptx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;(~14mb) (o Microsoft Office 2007 &amp;#233; necess&amp;#225;rio para abrir a apresenta&amp;#231;&amp;#227;o, um plugin de compatibilidade para vers&amp;#245;es anteriores do Office pode ser encontrada aqui: &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=941b3470-3ae9-4aee-8f43-c6bb74cd1466&amp;amp;displaylang=en" class="externalLink"&gt;http://www.microsoft.com/downloads/details.aspx?familyid=941b3470-3ae9-4aee-8f43-c6bb74cd1466&amp;amp;displaylang=en&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;);&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;14/09/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;nesta &amp;#250;ltima semana estive tentando fazer um benchmark do Cuda. Trata-se de um programa que resolve o problema das n-rainhas*, desenvolvido em Cuda e C&lt;u&gt;&lt;/u&gt;. O trabalho em quest&amp;#227;o foi feito pelo Vitor, e pode ser conferido em &lt;a href="http://vitorpamplona.com/wiki/An%C3%A1lise%20de%20Performance:%20C%20vs%20Cuda" class="externalLink"&gt;http://vitorpamplona.com/wiki/An%C3%A1lise%20de%20Performance:%20C%20vs%20Cuda&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;Nesse trabalho foi concluido que a implementa&amp;#231;&amp;#227;o em C&lt;u&gt;&lt;/u&gt; estava mais eficiente que a em Cuda. Entretanto fora utilizada a vers&amp;#227;o 1.0 do Cuda, e minha inten&amp;#231;&amp;#227;o era fazer um novo teste com a nova vers&amp;#227;o do compilador, para verificar eventuais melhorias de performance. Tamb&amp;#233;m gostaria de fazer os testes com diferentes configura&amp;#231;&amp;#245;es de hardware.&lt;br /&gt;Entretanto estive com bastantes dificuldades em fazer os testes funcionarem. Eles apresentaram um comportamento an&amp;#244;malo (leia-se imprevis&amp;#237;vel) na m&amp;#225;quina em que iniciei os testes, e atribui o problema &amp;#224; arquitetura 64bits da nova m&amp;#225;quina. Mudando para um processador 32 bits n&amp;#227;o tenho problemas com a compila&amp;#231;&amp;#227;o, entretanto estou tendo problemas com os kernels, que falham em sua execu&amp;#231;ao. Acredito ser um pequeno problema com a mudan&amp;#231;a do compilador (1.0 -&amp;gt; 2.2), mas ainda n&amp;#227;o consegui identific&amp;#225;-lo.&lt;br /&gt;Estarei postando aqui em breve um relat&amp;#243;rio de meus testes.&lt;br /&gt;&lt;br /&gt;Fora isso continuo estudando OpenCl, o que &amp;#233; bastante parecido com Cuda, assim que vou 'com as duas ao mesmo tempo'.&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;28/08/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estive estudando uma maneira de gerenciar automaticamente a inclus&amp;#227;o da DLL (como citado no post anterior). Postei algumas perguntas no blog da MSDN e obtive algumas respostas interessantes, que devem ser testadas nos proximos dias.&lt;br /&gt;&lt;br /&gt;Estive tamb&amp;#233;m estudando nessas &amp;#250;ltimas semanas &lt;b&gt;OpenCl&lt;/b&gt;.&lt;br /&gt;OpenCl &amp;#233; uma linguagem inicialmente criada pela Apple - e que teve como colaboradores a Intel, a nVidia e a AMD - para escrever programas que executem em ambientes heterogeneos, compostos de GPUs e CPUs.&lt;br /&gt;A linguagem foi 'abra&amp;#231;ada' pelo Kronos Group, que disponibilizou recentemente a especifica&amp;#231;&amp;#227;o da vers&amp;#227;o 1.0.&lt;br /&gt;Atualmente existem apenas vers&amp;#245;es beta dos drivers (visto que o kronos group somente disponibiliza a especifica&amp;#231;&amp;#227;o, cabe &amp;#224;s fabricantes de hardware gr&amp;#225;fico implementarem essa especifica&amp;#231;&amp;#227;o e fornecerem um compilador e um driver/sdk.&lt;br /&gt;&lt;br /&gt;Eu estou aqui testando com o driver beta da nvidia (apenas para desenvolvedores registrados). A implementa&amp;#231;&amp;#227;o da nVidia nada mais &amp;#233; que um 'mapeamento' da arquitetura CUDA para o OpenCl (creio que isso seja pr&amp;#243;ximo ao que a AMD/ATI est&amp;#225; fazendo, mapeando n&amp;#227;o para o CUDA mas para o Stream).&lt;br /&gt;&lt;br /&gt;Em CUDA, as fun&amp;#231;&amp;#245;es que se utilizam do paralelismo da GPU s&amp;#227;o conhecidas como &lt;i&gt;kernels&lt;/i&gt;.&lt;br /&gt;Kernels s&amp;#227;o executados por Streaming Multiprocessors (SMs). Cada SM, por sua vez, &amp;#233; composto por 8 Scalar Processors (SPs), os quais podem, cada um, executar simultaneamente at&amp;#233; 4 threads. Assim temos que um Streaming Multiprocessor pode executar simultaneamente at&amp;#233; 32 threads, o que chamaremos de &lt;i&gt;warp&lt;/i&gt;.&lt;br /&gt;Sempre que invocamos um kernel, especificamos para ele quantos &lt;i&gt;thread&lt;/i&gt; &lt;i&gt;blocks&lt;/i&gt; e quantas &lt;i&gt;threads&lt;/i&gt; &lt;i&gt;per&lt;/i&gt; &lt;i&gt;block&lt;/i&gt; queremos que esse kernel utilize. Cada SM encarrega-se da execu&amp;#231;&amp;#227;o de 1 thread block.&lt;br /&gt;Teoricamente, assim, se tivermos menos que 32 threads em um thread block estaremos 'perdendo processamento', pois n&amp;#227;o teremos preenchido o warp do SM. Se tivermos mais que 32 threads per block, entretanto, nossa situa&amp;#231;&amp;#227;o depender&amp;#225; da quantidade de mem&amp;#243;ria e de registradores que estar&amp;#227;o sendo utilizados. Funciona da seguinte forma: a CPU utiliza cache para esconder a latencia de mem&amp;#243;ria, i.e. para n&amp;#227;o termos que esperar sempre que os dados cheguem, n&amp;#243;s armazenamos-nos em uma cache. Na GPU escondemos a lat&amp;#234;ncia da mem&amp;#243;ria com computa&amp;#231;&amp;#245;es. Temos que a troca de contexto entre threads &amp;#233; muito veloz, assim ao inv&amp;#233;s de armazenarmos a mem&amp;#243;ria em uma grande cache, simplesmente mandamos outra thread executar enquanto esperamos, contanto que haja registradores livres no banco de registradores do SM.&lt;br /&gt;&lt;br /&gt;Em OpenCl temos a no&amp;#231;&amp;#227;o de &lt;i&gt;work-item&lt;/i&gt;s, que s&amp;#227;o mapeados para CUDA Threads, temos a no&amp;#231;&amp;#227;o de &lt;i&gt;work-groups&lt;/i&gt;, que s&amp;#227;o mapeados para thread blocks e por fim temos um NDRange, que &amp;#233; mapeado para um grid de thread blocks.&lt;br /&gt;O mapeamento &amp;#233; feito compilando OpenCl para o mesmo &amp;quot;bytecode&amp;quot;: PTX.&lt;br /&gt;&lt;br /&gt;Em breve estarei postando aqui trechos iniciais de c&amp;#243;digo em OpenCl, e espero estar fazendo alguns benchmarks com CUDA/OpenCl/CPU.&lt;br /&gt;&lt;br /&gt;Para maiores informa&amp;#231;&amp;#245;es a respeito das duas linguagens:
&lt;ul&gt;&lt;li&gt;Cuda:
&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.nvidia.com/object/cuda_home.html#" class="externalLink"&gt;http://www.nvidia.com/object/cuda_home.html#&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/CUDA" class="externalLink"&gt;http://en.wikipedia.org/wiki/CUDA&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ddj.com/hpc-high-performance-computing/207200659" class="externalLink"&gt;http://www.ddj.com/hpc-high-performance-computing/207200659&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;OpenCl
&lt;ul&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/OpenCL" class="externalLink"&gt;http://en.wikipedia.org/wiki/OpenCL&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.khronos.org/opencl/" class="externalLink"&gt;http://www.khronos.org/opencl/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.nvidia.com/object/cuda_opencl.html" class="externalLink"&gt;http://www.nvidia.com/object/cuda_opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ati.amd.com/technology/streamcomputing/opencl.html" class="externalLink"&gt;http://ati.amd.com/technology/streamcomputing/opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.openclworld.com/" class="externalLink"&gt;http://www.openclworld.com/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/07/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;Nesta semana estive com alguns problemas relativos &amp;#224; compatibilidade do debugger quando o projeto &amp;#233; levado a outros computadores. Esses problemas se deveram n&amp;#227;o &amp;#224; falta de compatibilidade do programa, mas sim do Package. Corrigi o problema, mas pretendo investigar a sua causa.&lt;br /&gt;Estou agora precisando ter acesso ao executavel gerado ap&amp;#243;s a compila&amp;#231;&amp;#227;o, estive dando uma olhada nisso nesta semana, sem muito sucesso. Al&amp;#233;m disso, preciso encontrar uma forma de manter sempre a DLL modificada como a acessivel pelo programa, ou seja, preciso de alguma forma manter a dll nas pastas do Visual Studio, no local onde o Package &amp;#233; instalado, e fazer com que tudo isso se ajeite na hora da instala&amp;#231;&amp;#227;o do pacote.&lt;br /&gt;Al&amp;#233;m desses pequenos problemas, continuo trabalhando na parte gr&amp;#225;fica (infelizmente n&amp;#227;o sou muito proficiente na cria&amp;#231;&amp;#227;o de interfaces amig&amp;#225;veis e bonitas) para integr&amp;#225;-la bem ao ambiente do Visual Studio. Ainda estou pensando em uma boa forma de dispor os compontentes, e em como melhorar a usabilidade do debugger.&lt;br /&gt;Fora isso ele se encontra bem integrado. &amp;#201; preciso fazer alguns testes, nos quais me dedicarei na pr&amp;#243;xima semana.&lt;br /&gt;&lt;br /&gt;At&amp;#233; la,&lt;br /&gt;&lt;br /&gt;Leonardo&lt;br /&gt;
&lt;h2&gt;08/07/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;Estou fazendo atualmente alguns ajustes automatizar mais o debugger, utilizando para isso as interface IVsRunningDocTableEvents, que implementa alguns m&amp;#233;todos para obter as notifica&amp;#231;&amp;#245;es sobre modifica&amp;#231;&amp;#245;es na IDE.&lt;br /&gt;Para poder passar a receber os eventos da IDE (que ser&amp;#227;o tratados pelos handlers da interface, a saber:
&lt;ul&gt;&lt;li&gt;int IVsRunningDocTableEvents.OnAfterAttributeChange&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterDocumentWindowHide&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterFirstDocumentLock&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterSave&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnBeforeDocumentWindowShow&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnBeforeLastDocumentUnlock&lt;/li&gt;&lt;/ul&gt;
)&lt;br /&gt;&lt;br /&gt;Esses eventos s&amp;#227;o importantes para que possamos ser notificados de modifica&amp;#231;&amp;#245;es importantes, como por exemplo saber quais s&amp;#227;o os documentos que est&amp;#227;o abertos.&lt;br /&gt;&lt;br /&gt;Para poder receber os eventos, devemos nos inscrever da seguinte forma:&lt;br /&gt;Declaramos inicialmente um cookie:
&lt;ul&gt;&lt;li&gt;uint cookie;&lt;/li&gt;&lt;/ul&gt;
E logo ap&amp;#243;s devemos declarar uma interface IVsRunningDocumentTable, e solicitar que ela avise sobre os eventos
&lt;ul&gt;&lt;li&gt;IVsRunningDocumentTable rdt = &lt;/li&gt;&lt;/ul&gt;
                (IVsRunningDocumentTable)Package.GetGlobalService(typeof(SVsRunningDocumentTable));
&lt;ul&gt;&lt;li&gt;rdt.AdviseRunningDocTableEvents(this, out dwCookie);&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Em breve, novas novidades.&lt;br /&gt;At&amp;#233;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;11/06/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;infelizemente, ap&amp;#243;s algum tempo de estudo em cima do debugger de exemplo, feito por Jackson Davis, dispon&amp;#237;vel em &lt;a href="http://code.msdn.microsoft.com/debugenginesample" class="externalLink"&gt;http://code.msdn.microsoft.com/debugenginesample&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;, e ap&amp;#243;s uma troca de e-mails com o mesmo, constatei que o desenvolvimento de uma debug engine para o VS, ou seja, o objetivo inicial de integrar totalmente o debugger de GLSL com o debugger do Visual Studio &amp;#233; demasiado complexa, visto que h&amp;#225; um grande n&amp;#250;mero de interfaces a implementar e que aparentemente o debugger de GLSL n&amp;#227;o &amp;#233; compat&amp;#237;vel com o modelo de debug engine que o Visual Studio espera. Com certeza ha uma maneira de realizar essa integra&amp;#231;ao, fazendo as devidas modifica&amp;#231;&amp;#245;es no debugger e implementando as interfaces requeridas pelo VS, mas esse trabalho levar&amp;#225; muito tempo.&lt;br /&gt;Portanto, dadas as condi&amp;#231;&amp;#245;es, optamos por desenvolver o depurador de forma externa ao depurador do Visual Studio, como j&amp;#225; vinha sendo feito em paralelo. Existe uma quantidade consideravel de melhorias que se podem fazer e &amp;#233; esse o atual objetivo.&lt;br /&gt;Tendo em vista o atual foco do trabalho, em pouco tempo espero estar postando alguns print screens e releases do debugger 'integrado'.&lt;br /&gt;&lt;br /&gt;Obrigado,&lt;br /&gt;&lt;br /&gt;Leonardo&lt;br /&gt;
&lt;h2&gt;26/05/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estou utilizando os objetos DTE e DTE2 para alguns testes. Ainda tive alguns problemas ap&amp;#243;s o &amp;#250;ltimo post para conseguir o objeto, mas agora essa j&amp;#225; &amp;#233; uma quest&amp;#227;o do passado.&lt;br /&gt;Estive nessas semanas estudando os objetos DTE e DTE2 e tamb&amp;#233;m estudando um projeto de exemplo de um depurador C&lt;u&gt;&lt;/u&gt; integrado ao Visual Studio. Os resultados desse estudo ainda n&amp;#227;o s&amp;#227;o vis&amp;#237;veis no depurador GLSL.&lt;br /&gt;Quanto a altera&amp;#231;oes no depurador, coloquei uma lista com os shaders sendo editados no projeto, de forma que o usu&amp;#225;rio possa escolher mais facilmente qual o shader a ser escolhido. Vou seguir com algumas altera&amp;#231;&amp;#245;es visuais desse estilo para deixar o debugger mais amig&amp;#225;vel.&lt;br /&gt;&lt;br /&gt;At&amp;#233;&lt;br /&gt;
&lt;h2&gt;12/05/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;ontem descobri uma solu&amp;#231;&amp;#227;o interessante para um pequeno problema que me atormentou por bastante tempo e que pelo visto atormenta bastante gente ainda.&lt;br /&gt;Para solucionar uma s&amp;#233;rie de quest&amp;#245;es ao desenvolver VSPackages, podemos utilizar o &amp;quot;automation object&amp;quot; DTE, que representa o objeto de mais alta hierarquia no ambiente EnvDTE, que possui referencias a todos os elementos da automa&amp;#231;&amp;#227;o do n&amp;#250;cleo do VS. Para tanto declaramos uma interface DTE, pertencente ao namespace EnvDTE (&amp;#233; necess&amp;#225;rio adicionar uma Reference ao projeto: EnvDTE), e utilizamos o m&amp;#233;todo GetService para recuperar o objeto DTE (ele ser&amp;#225; referenciado pela interface DTE que declaramos).&lt;br /&gt;Pretendo colocar mais explica&amp;#231;&amp;#245;es sobre o objeto DTE nos proximos post, mas agora quero me concentrar na explica&amp;#231;&amp;#227;o e solu&amp;#231;&amp;#227;o do problema que me atormentou.&lt;br /&gt;Eis que o seguinte c&amp;#243;digo &amp;#233; o respons&amp;#225;vel por declarar e recuperar o objeto DTE:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; EnvDTE;

DTE dte;

&lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Initialize() {
&lt;span style="color:Green;"&gt;//Inicializa&amp;#231;&amp;#245;es&lt;/span&gt;

&lt;span style="color:Blue;"&gt;this&lt;/span&gt;.dte = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SDTE)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; DTE;
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Entretanto, ap&amp;#243;s a execu&amp;#231;&amp;#227;o do trecho, dte continuava sempre com valor null, o que acabava gerando exce&amp;#231;&amp;#245;es e obviamente n&amp;#227;o era o que deveria estar acontecendo.&lt;br /&gt;Buscando na internet, encontrei no VSX Team Blog (o blog do pessoal do VSX (Visual Studio Extensibility)) a solu&amp;#231;&amp;#227;o para meu problema.&lt;br /&gt;O fato &amp;#233; que caso o ambiente n&amp;#227;o esteja totalmente carregado (em &amp;quot;zombie state&amp;quot;), a solicita&amp;#231;&amp;#227;o da referencia do objeto DTE retorna null. Como eu queria que o package fosse carregado juntamente com o VS (no startup), a inicializa&amp;#231;&amp;#227;o do package ocorria antes de o ambiente estar totalmente carregado, e dte continha sempre o valor null.&lt;br /&gt;Assim, a solu&amp;#231;&amp;#227;o proposta pelo pessoal do blog &amp;#233; a seguinte: utilizar a interface IVsShellPropertyEvents, implementando o handler OnShellPropertyChange, o qual faz o tracking do estado da IDE. A propriedade que diz se o VS est&amp;#225; zombie &amp;#233; a VSPROPID_Zombie.&lt;br /&gt;Segue abaixo a implementa&amp;#231;&amp;#227;o do blog do pessoal do VSX:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
      DTE dte;
      &lt;span style="color:Blue;"&gt;uint&lt;/span&gt; cookie;
      &lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Initialize()
      {
           &lt;span style="color:Blue;"&gt;base&lt;/span&gt;.Initialize();
           IVsShell shellService = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsShell)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; IVsShell;
           &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (shellService != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
                ErrorHandler.ThrowOnFailure(shellService.AdviseShellPropertyChanges(&lt;span style="color:Blue;"&gt;this&lt;/span&gt;,&lt;span style="color:Blue;"&gt;out&lt;/span&gt; cookie));
           ...
        }

        &lt;span style="color:Blue;"&gt;#region&lt;/span&gt; IVsShellPropertyEvents Members

        &lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;int&lt;/span&gt; OnShellPropertyChange(&lt;span style="color:Blue;"&gt;int&lt;/span&gt; propid, &lt;span style="color:Blue;"&gt;object&lt;/span&gt; &lt;span style="color:Blue;"&gt;var&lt;/span&gt;)
        {
            &lt;span style="color:Green;"&gt;// when zombie state changes to false, finish package initialization&lt;/span&gt;
            &lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((&lt;span style="color:Blue;"&gt;int&lt;/span&gt;)__VSSPROPID.VSSPROPID_Zombie == propid)
            {
                &lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((&lt;span style="color:Blue;"&gt;bool&lt;/span&gt;)&lt;span style="color:Blue;"&gt;var&lt;/span&gt; == &lt;span style="color:Blue;"&gt;false&lt;/span&gt;)
                {
                    &lt;span style="color:Green;"&gt;// zombie state dependent code&lt;/span&gt;
                    &lt;span style="color:Blue;"&gt;this&lt;/span&gt;.dte = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SDTE)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; DTE;
                    &lt;span style="color:Green;"&gt;// eventlistener no longer needed&lt;/span&gt;
                    IVsShell shellService = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsShell)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; IVsShell;
                    &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (shellService != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
                        ErrorHandler.ThrowOnFailure(shellService.UnadviseShellPropertyChanges(&lt;span style="color:Blue;"&gt;this&lt;/span&gt;.cookie));
                    &lt;span style="color:Blue;"&gt;this&lt;/span&gt;.cookie = 0;
                }
            }

            &lt;span style="color:Blue;"&gt;return&lt;/span&gt; VSConstants.S_OK;

        }

        &lt;span style="color:Blue;"&gt;#endregion&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Esse artigo pode ser encontrado em &lt;a href="http://blogs.msdn.com/vsxteam/archive/2008/06/09/dr-ex-why-does-getservice-typeof-envdte-dte-return-null.aspx" class="externalLink"&gt;http://blogs.msdn.com/vsxteam/archive/2008/06/09/dr-ex-why-does-getservice-typeof-envdte-dte-return-null.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Nos proximos posts estarei descrevendo mais a fundo a parte t&amp;#233;cnica do VS que estudei at&amp;#233; agora, e introduzirei alguns dos problemas futuros que pretendo estar resolvendo.&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;06/05/09&lt;/h2&gt;Ol&amp;#225;,&lt;br /&gt;nestas ultimas semanas estive um pouco sobrecarregado, e n&amp;#227;o tive muito tempo para escrever no blog. A primeira etapa da depura&amp;#231;&amp;#227;o j&amp;#225; esta concluida, entretanto restam alguns bugs relativos ao depurador que devem ser resolvidos antes de ser lan&amp;#231;ado um release do plug-in.&lt;br /&gt;Venho trabalhando na parte mais profunda da integra&amp;#231;&amp;#227;o.&lt;br /&gt;Al&amp;#233;m da mera quest&amp;#227;o de mapear as funcionalidades do depurador para a IDE (que n&amp;#227;o &amp;#233; trivial), restam alguns problemas que surgem do fato de que algumas features existentes no VS n&amp;#227;o se encontram atualmente no depurador (como por exemplo a utiliza&amp;#231;&amp;#227;o de breakpoints). Essas funcionalidades dever&amp;#227;o ser implementadas em breve.&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/04/09&lt;/h2&gt;Oi,&lt;br /&gt;nesta semana finalizei uma primeira integra&amp;#231;&amp;#227;o. Neste primeiro est&amp;#225;gio temos, como j&amp;#225; foi dito, o depurador da B&amp;#225;rbara executando sobre o Visual Studio.&lt;br /&gt;H&amp;#225; ainda uma s&amp;#233;rie de melhorias que devem ser feitas sobre esta integra&amp;#231;&amp;#227;o:
&lt;ul&gt;&lt;li&gt;Melhorias na estrutura&amp;#231;&amp;#227;o e organiza&amp;#231;&amp;#227;o do c&amp;#243;digo;&lt;/li&gt;
&lt;li&gt;Remo&amp;#231;&amp;#227;o de alguns bugs;&lt;/li&gt;
&lt;li&gt;Melhor organiza&amp;#231;&amp;#227;o visual;&lt;/li&gt;&lt;/ul&gt;
At&amp;#233; o fim desta semana planejo ter uma vers&amp;#227;o utilizavel do depurador, melhor organizada visualmente, com algumas funcionalidades a mais (no que toca &amp;#224; integra&amp;#231;&amp;#227;o, por exemplo que o depurador saiba qual o shader que deve ser depurado automaticamente, assim como o programa opengl.&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;20/04/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estou tendo alguns problemas na integra&amp;#231;&amp;#227;o, que derivam diretamente de d&amp;#250;vidas com rela&amp;#231;&amp;#227;o ao depurador desenvolvido pela Barbara.&lt;br /&gt;A id&amp;#233;ia desta primeira integra&amp;#231;&amp;#227;o &amp;#233; bastante simples, uma simples adi&amp;#231;&amp;#227;o do depurador da barbara sobre o VS. A id&amp;#233;ia &amp;#233; que ap&amp;#243;s essa etapa seja construido incrementalmente o depurador integrado. Nesse ponto temos algumas dificuldades, como por exemplo que o depurador n&amp;#227;o suporta a coloca&amp;#231;&amp;#227;o de breakpoints, mas executa sempre passo a passo, de forma que n&amp;#227;o se pode definir de forma mais flexivel o fluxo do programa.&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;10/04/09&lt;/h2&gt;Ol&amp;#225;,&lt;br /&gt;nesta semana estive trabalhando na efetiva integra&amp;#231;&amp;#227;o do Depurador GLSL para o VS2008. A id&amp;#233;ia inicial inserir apenas o depurador de forma externa ao depurador do Visual Studio, o que &amp;#233; uma tarefa mais simples e deve ser terminada at&amp;#233; o final da semana. Nos proximos posts estarei publicando screenshots e maiores explica&amp;#231;&amp;#245;es sobre essa integra&amp;#231;&amp;#227;o. Esse trabalho tem a vantagem de que o depurador estar&amp;#225; rapidamente pronto para ser utilizado, entretanto ele n&amp;#227;o estara integrado com o depurador do Visual Studio. Para acess&amp;#225;-lo haver&amp;#227;o menus e janelas exclusivas que se encarregar&amp;#227;o de realizar todo o processo.&lt;br /&gt;Ap&amp;#243;s terminar essa primeira etapa de integra&amp;#231;&amp;#227;o, pretendo construir uma Debug Engine que se comunique com a SDM e torne o processo de depura&amp;#231;&amp;#227;o transparente ao usu&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;01/04/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;nas semanas anteriores eu estive estudando o desenvolvimento de VSPackages gen&amp;#233;ricos, como uma forma de me familiarizar com eles. Nesta semana, e nas que vir&amp;#227;o, me voltei efetivamente para o VSDebugger e como extend&amp;#234;-lo.&lt;br /&gt;&lt;br /&gt;Basicamente o debugger do visual studio &amp;#233; composto de tr&amp;#234;s partes:
&lt;ul&gt;&lt;li&gt;Interface com o usu&amp;#225;rio (UI), que permite, por exemplo, que sejam colocados breakpoints, que o codigo seja executado instru&amp;#231;&amp;#227;o a instru&amp;#231;&amp;#227;o, etc.&lt;/li&gt;
&lt;li&gt;SDM (Session Debug Manager), que &amp;#233; basicamente quem gerencia as Debug Engines. Pode ser visto como um multiplexador de Debug Engines, al&amp;#233;m de fazer a comunica&amp;#231;&amp;#227;o com a UI. A SDM &amp;#233; implementada pelo VS e n&amp;#227;o ser&amp;#225; alterada.&lt;/li&gt;
&lt;li&gt;Debug Engine (DE), que &amp;#233; o elemento que efetivamente faz a depura&amp;#231;&amp;#227;o do programa, e se comunica com a SDM. &amp;#201; aqui que ser&amp;#225; introduzido o depurador de GLSL.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Assim, teremos que construir uma DE que incorpore o depurador desenvolvido pela B&amp;#225;rbara. Para construir uma DE, s&amp;#227;o necess&amp;#225;rios alguns passos:
&lt;ul&gt;&lt;li&gt;Primeiro devemos registrar nossa DE no Visual Studio, permitindo que ele a reconhe&amp;#231;a e utilize;&lt;/li&gt;
&lt;li&gt;Nossa DE deve, quando solicitado pela SDM, &amp;quot;conectar-se&amp;quot; ao programa a ser depurado. Isso ocorre quando o usu&amp;#225;rio escolhe depurar o programa. Ocorre ent&amp;#227;o uma troca de mensagens entre a SDM e as DEs;&lt;/li&gt;
&lt;li&gt;Agora que nossa DE est&amp;#225; &amp;quot;conectada&amp;quot; ao programa efetivamente podemos nos concentrar em depurar o programa. Esta etapa consiste em:
&lt;ul&gt;&lt;li&gt;Controlar o fluxo de execu&amp;#231;&amp;#227;o, respeitando breakpoints e execu&amp;#231;&amp;#227;o step-by-step;&lt;/li&gt;
&lt;li&gt;Comunicar-se com a SDM, fazendo com que tanto o VS quanto o usu&amp;#225;rio tenham um feedback da depura&amp;#231;&amp;#227;o;&lt;/li&gt;
&lt;li&gt;Al&amp;#233;m disso temos que permitir:
&lt;ul&gt;&lt;li&gt;A cria&amp;#231;&amp;#227;o/dele&amp;#231;&amp;#227;o de breakpoints;&lt;/li&gt;
&lt;li&gt;A inser&amp;#231;&amp;#227;o de watches;&lt;/li&gt;
&lt;li&gt;A visualiza&amp;#231;&amp;#227;o da pilha de chamadas;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;A seguir devemos nos desconectar do programa e solicitar &amp;#224; SDM para que o mesmo seja terminado;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Neste momento estou estudando um pouco mais o trabalho da B&amp;#225;rbara. Minhas d&amp;#250;vidas se concentram em como exatamente integrar todo o sistema de debugging do Visual Studio ao depurador que j&amp;#225; foi desenvolvido. Nos pr&amp;#243;ximos posts procurarei explicar um pouco melhor o funcionamento do mecanismo de depura&amp;#231;&amp;#227;o do VS, al&amp;#233;m de tentar aproximar um pouco mais os dois debuggers.&lt;br /&gt;&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;25/03/09 - Hello World&lt;/h2&gt;Nesta semana continuei a estudar o desenvolvimento de um Package para o VS2008. O estudo foi dirigido basicamente aos procedimentos de cria&amp;#231;&amp;#227;o e ao funcionamento dos recursos gerados pelo wizard.&lt;br /&gt;&lt;br /&gt;Para iniciar o desenvolvimento de um VSPackage, ap&amp;#243;s baixar o SDK do Visual Studio, &amp;#233; utilizar o wizard de cria&amp;#231;&amp;#227;o de package, que se encarrega de gerar o c&amp;#243;digo base, deixando para n&amp;#243;s apenas o desenvolvimento do Package.&lt;br /&gt;Assim, ap&amp;#243;s definir o nome de nosso Package, somos perguntados a respeito de algumas coisas sobre o ele: a linguagem em que o desenvolveremos, se queremos uma Tool Window, um Menu Tool, etc.&lt;br /&gt;Para construir o Hello World utilizei C# e criei tanto uma Tool Window quanto um Menu Tool.&lt;br /&gt;Os resultados foram os seguintes:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Window&lt;/b&gt; &lt;b&gt;Tool:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63149" alt="windowTool.bmp" title="windowTool.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63150" alt="windowTool2.bmp" title="windowTool2.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo Fonte&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; okButton_Click(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, System.EventArgs e)
        {
            MessageBox.Show(&lt;span style="color:#A31515;"&gt;&amp;quot;Seu nome &amp;#233; &amp;quot;&lt;/span&gt; + nameBox.Text.ToString(), &lt;span style="color:#A31515;"&gt;&amp;quot;Seu nome&amp;quot;&lt;/span&gt;, MessageBoxButtons.OK);
        }

        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; limparButton_Click(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, System.EventArgs e)
        {
            nameBox.Text = &lt;span style="color:#A31515;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;;
        }

&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Command Tool:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63151" alt="cmdTool.bmp" title="cmdTool.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo fonte do command:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; MenuItemCallback(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, EventArgs e)
        {
            &lt;span style="color:Green;"&gt;// Show a Message Box to prove we were here&lt;/span&gt;
            IVsUIShell uiShell = (IVsUIShell)GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsUIShell));
            Guid clsid = Guid.Empty;
            &lt;span style="color:Blue;"&gt;int&lt;/span&gt; result;
            Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(uiShell.ShowMessageBox(
                       0,
                       &lt;span style="color:Blue;"&gt;ref&lt;/span&gt; clsid,
                       &lt;span style="color:#A31515;"&gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;,
                       &lt;span style="color:Blue;"&gt;string&lt;/span&gt;.Format(CultureInfo.CurrentCulture, &lt;span style="color:#A31515;"&gt;&amp;quot;Hello World - Este &amp;#233; um menuTool&amp;quot;&lt;/span&gt;),
                       &lt;span style="color:Blue;"&gt;string&lt;/span&gt;.Empty,
                       0,
                       OLEMSGBUTTON.OLEMSGBUTTON_OK,
                       OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST,
                       OLEMSGICON.OLEMSGICON_INFO,
                       0,        &lt;span style="color:Green;"&gt;// false&lt;/span&gt;
                       &lt;span style="color:Blue;"&gt;out&lt;/span&gt; result));
        }
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Nos proximos posts estarei explicando com mais detalhes o funcionamento desses elementos. Atualmente estou buscando algo mais proximo do debugger, assim que possivelmente nos proximos posts n&amp;#227;o estarei mais lidando com exemplos gen&amp;#233;ricos, mas com algo mais focado no debugger em si.&lt;br /&gt;Uma &amp;#243;tima refer&amp;#234;ncia (em ingles) &amp;#233; &lt;a href="http://learnvsxnow.codeplex.com/" class="externalLink"&gt;http://learnvsxnow.codeplex.com/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;17/03/09&lt;/h2&gt;Oi pessoal,&lt;br /&gt;sou o Leonardo e este &amp;#233; meu primeiro post aqui.&lt;br /&gt;Atualmente, como a Barbara comentou, estou estudando o desenvolvimento de um &amp;quot;plug-in&amp;quot; para o Visual Studio, que permita a integra&amp;#231;&amp;#227;o do trabalho dela com o ambiente de desenvolvimento, facilitando assim o trabalho de depura&amp;#231;&amp;#227;o.&lt;br /&gt;A id&amp;#233;ia &amp;#233; tornar o depurador natural ao usu&amp;#225;rio do VS.&lt;br /&gt;&lt;br /&gt;O desenvolvimento se far&amp;#225; a partir de VSPackages, que s&amp;#227;o a ferramenta de extensibilidade mas completa que a Microsoft prov&amp;#234; para o Visual Studio.&lt;br /&gt;&lt;br /&gt;Mais informa&amp;#231;&amp;#245;es sobre Visual Studio Extensibility, al&amp;#233;m do download dos SDKs do VS2005 e VS208, podem ser encontradas aqui: &lt;a href="http://msdn.microsoft.com/en-us/vsx/default.aspx" class="externalLink"&gt;http://msdn.microsoft.com/en-us/vsx/default.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; (Visual Studio Extensibility Developer Center).&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;08/03/2009&lt;/h2&gt;Nesta semana trabalhei corrigindo problemas na interface e procurei deixar o c&amp;#243;digo do depurador menos &amp;quot;duro&amp;quot;. Como por exemplo, poder abrir os arquivos em qualquer ordem e n&amp;#227;o primeiro um tipo de shader e depois o outro.&lt;br /&gt;
&lt;h2&gt;24/02/2009&lt;/h2&gt;Em virtude da troca de bolsistas, optamos por focar no desenvolvimento do plugin para o Visual Studio. Desta forma, o Leonardo est&amp;#225; estudando o desenvolvimento de plugins, enquanto eu estou arrumando o c&amp;#243;digo para que esta integra&amp;#231;&amp;#227;o possa ser feita.&lt;br /&gt;
&lt;h2&gt;18/02/2009&lt;/h2&gt;Fui aprovada para o Mestrado em Ci&amp;#234;ncia da Computa&amp;#231;&amp;#227;o - UFRGS, desta forma, a partir de mar&amp;#231;o estarei afastada do projeto. Quem ir&amp;#225; dar continuidade ao projeto &amp;#233; o aluno no quinto semestre de gradua&amp;#231;&amp;#227;o do curso de &lt;br /&gt;Ci&amp;#234;ncia da Computa&amp;#231;&amp;#227;o - UFRGS, Leonardo Chatain. Seja bem vindo, Leonardo!&lt;br /&gt;
&lt;h2&gt;18/01/2009&lt;/h2&gt;Como disse no &amp;#250;ltimo post, comecei a trabalhar na integra&amp;#231;&amp;#227;o da ferramenta com outras. &lt;br /&gt;A ferramenta com a qual estou fazendo integra&amp;#231;&amp;#227;o &amp;#233; a Shader Designer. A principal dificuldade encontrada at&amp;#233; o momento est&amp;#225; sendo portar o projeto da Shader Designer do Microsoft Visual Studio 2003 para o 2008 (ambiente em que foi desenvolvido o depurador). Estou tendo que re-escrever praticamente todo o c&amp;#243;digo. Al&amp;#233;m de que, o Shader Designer utiliza uma s&amp;#233;rie de c&amp;#243;digos fontes e de bibliotecas de terceiros (vide abaixo) que tamb&amp;#233;m est&amp;#227;o sendo portados. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digos Fontes de terceiros&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;a) 3DLabs GLSL Open Source Compiler &lt;br /&gt;&lt;br /&gt;b) Algumas fun&amp;#231;&amp;#245;es da &amp;quot;Matrix and Quaternion fAQ&amp;quot; &lt;br /&gt;&lt;br /&gt;c) AVI exporter &lt;br /&gt;&lt;br /&gt;d) GLEW Extensions manager.&lt;br /&gt;&lt;br /&gt;e) MeshMender da Nvidia&lt;br /&gt;&lt;br /&gt;f) DEV-IL&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Bibliotecas de terceiros&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;a) Compona's SyntaxBox. &lt;br /&gt;&lt;br /&gt;b) Flexporter&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;15/12/2008&lt;/h2&gt;Nestas &amp;#250;ltimas semanas escrevi e apresentei um trabalho acad&amp;#234;mico sobre o assunto. A apresenta&amp;#231;&amp;#227;o pode ser obtida &lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=51900';"&gt;aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Tamb&amp;#233;m foram acrescentadas novas funcionalidades:
&lt;ul&gt;&lt;li&gt;Permite ao usu&amp;#225;rio optar por depurar:
&lt;ul&gt;&lt;li&gt;Apenas o shader;&lt;/li&gt;
&lt;li&gt;Apenas o programa OpenGL hospedeiro;&lt;/li&gt;
&lt;li&gt;Ambos.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;ul&gt;&lt;li&gt;Permite visualizar o valor atualizado das vari&amp;#225;veis que j&amp;#225; foram depuradas&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Nas pr&amp;#243;ximas semanas, vou iniciar o estudo sobre desenvolvimento de plugins e come&amp;#231;ar a integra&amp;#231;&amp;#227;o da ferramenta.&lt;br /&gt;
&lt;h2&gt;30/11/2008&lt;/h2&gt;Como dito no post anterior, foram muitas as dificuldades encontradas na utiliza&amp;#231;&amp;#227;o de extens&amp;#245;es para captura de dados da placa gr&amp;#225;fica.&lt;br /&gt;Para que outras pessoas que necessitem utilizar estas extens&amp;#245;es n&amp;#227;o enfrentem o mesmo problema (principalmente pela falta de documenta&amp;#231;&amp;#227;o e de exemplos de uso), coloquei na p&amp;#225;gina &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Capturing%20Data%20From%20Graphics%20Hardware&amp;referringTitle=Blog"&gt;Capturing Data From Graphics Hardware&lt;/a&gt;, uma explica&amp;#231;&amp;#227;o das extens&amp;#245;es utilizadas com exemplos. &lt;br /&gt;&lt;br /&gt;O depurador foi aprimorado. Agora &amp;#233; poss&amp;#237;vel n&amp;#227;o apenas ver o resultado da vari&amp;#225;vel que est&amp;#225; sendo depurada, mas tamb&amp;#233;m das fun&amp;#231;&amp;#245;es pr&amp;#233;-definidas da OpenGL Al&amp;#233;m disto, foi escrito um trabalho acad&amp;#234;mico sobre o assunto, que ap&amp;#243;s sua apresenta&amp;#231;&amp;#227;o, tamb&amp;#233;m estar&amp;#225; dispon&amp;#237;vel aqui no CodePlex.&lt;br /&gt;&lt;br /&gt;Em breve tamb&amp;#233;m estarei disponibilizando um realease do depurador.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;30/10/2008 - Finishing the Debugger&lt;/h2&gt;Durante este m&amp;#234;s me foquei em terminar o depurador GLSL.&lt;br /&gt;Foram muitas as dificuldades encontradas, principalmente na utiliza&amp;#231;&amp;#227;o de extens&amp;#245;es para capturar a sa&amp;#237;da dos processadores de v&amp;#233;rtices e de fragmentos.&lt;br /&gt;Foram implementados 3 m&amp;#243;dulos:
&lt;ul&gt;&lt;li&gt;Wrapper OpenGL -&amp;gt; respons&amp;#225;vel por capturar as opera&amp;#231;&amp;#245;es OpenGL realizadas pelo programa OpenGL hospedeiro e inserir os c&amp;#243;digos necess&amp;#225;rios para depura&amp;#231;&amp;#227;o;&lt;/li&gt;
&lt;li&gt;Parser GLSL -&amp;gt; respons&amp;#225;vel por re-escrever o c&amp;#243;digo do shader GLSL de modo a inserir as vari&amp;#225;veis de depura&amp;#231;&amp;#227;o necess&amp;#225;rias&lt;/li&gt;
&lt;li&gt;Interfce Gr&amp;#225;fica -&amp;gt; respons&amp;#225;vel por interligar e utilizar os resultados obtidos nos demais m&amp;#243;dulos, al&amp;#233;m de, &amp;#233; claro, ser a interface com o usu&amp;#225;rio.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Este trabalho foi apresentado no &lt;a href="http://www.propesq.ufrgs.br/sic2008/index.htm" class="externalLink"&gt;XX Sal&amp;#227;o de IC - UFRGS&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. A apresenta&amp;#231;&amp;#227;o pode ser baixada &lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=47908';"&gt;aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Para as pr&amp;#243;ximas semanas pretendo continuar trabalhando no aprimoramento da ferramenta e escrever um documento mais detalhado sobre seu desenvolvimento.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;30/09/2008 - GLSL Debugger&lt;/h2&gt;
Passei algum tempo sem postar no blog. Durante este tempo estava trabalhando em uma nova etapa do projeto, o desenvolvimento de um plugin de depura&amp;#231;&amp;#227;o de GLSL para o Visual Studio. Maiores detalhes do andamento e da descri&amp;#231;&amp;#227;o desta etapa podem ser encontrados em &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=GLSL%20Debugger&amp;referringTitle=Blog"&gt;GLSL Debugger&lt;/a&gt;.&lt;br /&gt;
&lt;h2&gt;18/08/2008&lt;/h2&gt;GLSL n&amp;#227;o possui suporte &amp;#224; cast impl&amp;#237;cito (ex: vec4 color = 0.5;) assim, acrescentei o cast explicito (ex: vec4 color = vec4(0.5); )&lt;br /&gt;&lt;br /&gt;Continuei com os testes do programa. A principal dificuldade encontrada nos testes &amp;#233; a valida&amp;#231;&amp;#227;o. Por enquanto, o m&amp;#233;todo utilizado para os testes consiste em pegar um c&amp;#243;digo HLSL v&amp;#225;lido, converter e testar em um compilador GLSL se o c&amp;#243;digo gerado &amp;#233; v&amp;#225;lido ou n&amp;#227;o. Se n&amp;#227;o for, o programa &amp;#233; corrigido. Ou seja, por falta de uma BNF oficial da HLSL, nossos testes s&amp;#227;o baseados em exemplos. O que n&amp;#227;o &amp;#233; o ideal. A id&amp;#233;ia &amp;#233; que a pr&amp;#243;xima etapa de testes seja realizada comparando as imagens geradas. Ou seja, ser&amp;#227;o obtidas imagens executando o shader HLSL e estas ser&amp;#227;o comparadas com as imagens obtidas atrav&amp;#233;s da execu&amp;#231;&amp;#227;o do shader GLSL. A diferen&amp;#231;a entre estas imagens nos dir&amp;#225; o percentual de erro obtido na convers&amp;#227;o. &amp;#201; mais uma forma de validar o programa, por&amp;#233;m, o fato dos testes serem baseados em exemplos persiste. Para que este fator n&amp;#227;o seja t&amp;#227;o relevante, estamos utilizando uma gama variada de exemplos.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;04/08/2008&lt;/h2&gt;Como o programa estava dispon&amp;#237;vel apenas em vers&amp;#245;es de linha de comando, desenvolvi uma vers&amp;#227;o que apresenta uma interface gr&amp;#225;fica simplificada. Com esta interface, basta o usu&amp;#225;rio carregar o c&amp;#243;digo HLSL e clicar em converter. Os c&amp;#243;digos s&amp;#227;o exibidos lado &amp;#224; lado, facilitando a visualiza&amp;#231;&amp;#227;o pelo usu&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;Esta interface apresenta um limitante, que &amp;#233; o fato de ser compat&amp;#237;vel apenas com sistemas Windows. Por&amp;#233;m, em breve, pretendo desenvolver uma vers&amp;#227;o compat&amp;#237;vel com outros sistemas.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;24/07/2008&lt;/h2&gt;GLSL n&amp;#227;o apresenta suporte ao comando &amp;quot;Switch&amp;quot;. Desta forma, fiz uma fun&amp;#231;&amp;#227;o que substitui este comando por &amp;quot;If..else&amp;quot;.&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;        switch ( teste ) {
    			case 0: k++; return teste; 
    			case 1: return teste; 
    			case 2: t++; return teste; 
    			default: { 
    				teste++;
       			} 
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;      if (teste == 0) { k++; return teste; }
      else if (teste == 1) { return teste;}
      else if (teste == 2) { t++; return teste; }
      else { teste++;  }
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;GLSL n&amp;#227;o permite atribui&amp;#231;&amp;#245;es para elementos dos vetores, se estes vetores forem vari&amp;#225;veis to tipo &amp;quot;varying&amp;quot;. Ent&amp;#227;o, fiz uma fun&amp;#231;&amp;#227;o que cria uma vari&amp;#225;vel tempor&amp;#225;ria, efetua a atribui&amp;#231;&amp;#227;o e ent&amp;#227;o atribui o valor &amp;#224; vari&amp;#225;vel original.&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;  float4 MyShader( float2 Tex : TEXCOORD0 ) : COLOR0
{
    float4 Color;
    
    Color = float4(1.0,1.0,1.0,1.0);
    Color.a;
    Color.a = 0.1;
    Color.rgb = float3(0.5f);

    Tex.y = Tex.y + (sin(timeraslow)*0.01);
    Tex.x = Tex.x + (cos(timeraslow)*0.01);
    Color = tex2D( g_samSrcColor, Tex.xy);

    Color -= tex2D( g_samSrcColor, Tex.xy-0.001)*2.0f;
    Color += tex2D( g_samSrcColor, Tex.xy+0.001)*2.0f;
    Color.rgb = float3((Color.r+Color.g+Color.b)/3.0f);   	
   	
    return Color;
}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt; varying vec2 Tex;

void main( )
{
    vec4 Color;
    
    Color = vec4(1.0,1.0,1.0,1.0);
    Color.a;
    Color.a = 0.1;
    Color.rgb = vec3(0.5); //n&amp;#227;o necessita de vari&amp;#225;vel tempor&amp;#225;ria pois n&amp;#227;o &amp;#233; varying

    vec2 tempTex = Tex; //como Tex era varying foi criada uma vari&amp;#225;vel tempor&amp;#225;ria 

    tempTex.y = Tex.y + (sin(timeraslow)*0.01);
    Tex=tempTex;
    tempTex.x = Tex.x + (cos(timeraslow)*0.01);
    Tex=tempTex;
    Color = tex2D( g_samSrcColor, Tex.xy);

    Color -= tex2D( g_samSrcColor, Tex.xy-0.001)*2.0;
    Color += tex2D( g_samSrcColor, Tex.xy+0.001)*2.0;
    Color.rgb = vec3((Color.r+Color.g+Color.b)/3.0));   	
   	
    gl_FragColor = Color;
}
&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;09/07/2008&lt;/h2&gt;Acrescentei a convers&amp;#227;o das fun&amp;#231;&amp;#245;es intr&amp;#237;nsicas. Para as fun&amp;#231;&amp;#245;es intr&amp;#237;nsicas de HLSL que n&amp;#227;o s&amp;#227;o suportadas pela GLSL (vide &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Differences%20Between%20HLSL%20and%20GLSL&amp;referringTitle=Blog"&gt;Differences Between HLSL and GLSL&lt;/a&gt;), &amp;#233; emitida uma mensagem de aviso ao usu&amp;#225;rio.  GLSL tamb&amp;#233;m n&amp;#227;o suporta a letra 'f' ap&amp;#243;s um n&amp;#250;mero do tipo float (ex: 1.0f), ent&amp;#227;o, inseri uma fun&amp;#231;&amp;#227;o que remove este 'f' do n&amp;#250;mero. &lt;br /&gt;&lt;br /&gt;Iniciei tamb&amp;#233;m a fase de testes do programa. Para isto estou utilizando os shaders  &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Parsing%20Shaders&amp;referringTitle=Blog"&gt;Parsing Shaders&lt;/a&gt;. Ap&amp;#243;s converter, executo o arquivo gerado no software &lt;a href="http://www.opengl.org/sdk/tools/ShaderDesigner" class="externalLink"&gt;Shader Designer&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. Este software &amp;#233; um editor/compilador de GLSL. Assim, atrav&amp;#233;s de sua sa&amp;#237;da, posso verificar se o c&amp;#243;digo GLSL gerado &amp;#233; v&amp;#225;lido ou n&amp;#227;o e corrigir os problemas encontrados.&lt;br /&gt;&lt;br /&gt;A vers&amp;#227;o mais atual dos fontes do projeto encontra-se &lt;a href="http://www.codeplex.com/hl2glsl/SourceControl/ListDownloadableCommits.aspx" class="externalLink"&gt;dispon&amp;#237;vel&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;04/07/2008&lt;/h2&gt;Fiz algumas altera&amp;#231;&amp;#245;es na gram&amp;#225;tica e acrescentei novas fun&amp;#231;&amp;#245;es para tratar estas altera&amp;#231;&amp;#245;es.&lt;br /&gt;&lt;br /&gt;Altera&amp;#231;&amp;#245;es na gram&amp;#225;tica:&lt;br /&gt;*Reconhecimento do par&amp;#226;metro &amp;quot;: Register&amp;quot;;&lt;br /&gt;*Reconhecimento do par&amp;#226;metro &amp;quot;: Packoffset&amp;quot;;&lt;br /&gt;*Reconhecimento do operador un&amp;#225;rio &amp;quot;!&amp;quot;;&lt;br /&gt;*Reconhecimento do tipo &amp;quot;uint&amp;quot;.&lt;br /&gt;&lt;br /&gt;GLSL n&amp;#227;o apresenta suporte para acesso &amp;#224; registradores. Assim, os par&amp;#226;metros &amp;quot;register&amp;quot; e &amp;quot;packoffset&amp;quot; n&amp;#227;o podem ser utilizados. A medida adotada para solucionar este problema &amp;#233; avisar ao usu&amp;#225;rio deste fato e perguntar se ele deseja remover estes par&amp;#226;metros. Caso ele opte por n&amp;#227;o remover, um aviso de que o c&amp;#243;digo gerado ser&amp;#225; inconsistente &amp;#233; emitido.&lt;br /&gt;&lt;br /&gt;O caso do tipo &amp;quot;uint&amp;quot; &amp;#233; similar, pois tamb&amp;#233;m n&amp;#227;o &amp;#233; suportado pela GLSL. S&amp;#243; que ao inv&amp;#233;s de remover a vari&amp;#225;vel, a op&amp;#231;&amp;#227;o dada ao usu&amp;#225;rio &amp;#233; a de troc&amp;#225;-lo pelo tipo int. &lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;18/06/2008&lt;/h2&gt;Passei a utilizar o Source Code Client do CodePlex para disponibilizar o c&amp;#243;digo fonte.&lt;br /&gt;&lt;br /&gt;Acrescentei as fun&amp;#231;&amp;#245;es para tratar &amp;quot;return&amp;quot; e o tipo da fun&amp;#231;&amp;#227;o &amp;quot;main&amp;quot;.&lt;br /&gt;&lt;br /&gt;Em GLSL &amp;#233; necess&amp;#225;rio uma fun&amp;#231;&amp;#227;o void main() que &amp;#233; de onde iniciar&amp;#225; a execu&amp;#231;&amp;#227;o.  Em HLSL, isto n&amp;#227;o &amp;#233; necess&amp;#225;rio.&lt;br /&gt;Assim, &amp;#233; preciso substituir o nome da fun&amp;#231;&amp;#227;o em HLSL por &amp;quot;main&amp;quot; e o tipo da fun&amp;#231;&amp;#227;o por void. O tipo da fun&amp;#231;&amp;#227;o deve ser salvo pois ele ser&amp;#225; utilizado na sa&amp;#237;da da fun&amp;#231;&amp;#227;o.  &lt;br /&gt;&lt;br /&gt;Como a fun&amp;#231;&amp;#227;o em GLSL &amp;#233; do tipo void, ela n&amp;#227;o tem mais o &amp;quot;return&amp;quot;.  Sua sa&amp;#237;da vai ser determinada de acordo com o tipo e os par&amp;#226;metros sem&amp;#226;nticos da fun&amp;#231;&amp;#227;o original, &lt;br /&gt;&lt;br /&gt;Ex: &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;float4 pixelShader( float4 color):COLOR
{
          float4 teste =float4(0,1,0,0);
          float4 tes   = color + teste;

          return tes;
} &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;varying vec4 color;

void main() { 

	vec4 teste = vec4(0,1,0,0);
	vec4 tes   = color + teste;
	
	gl_FragColor = vec4(tes) ;  
} &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;02/06/2008&lt;/h2&gt;
Disponibilizei os fontes em desenvolvimento do projeto na sess&amp;#227;o Releases nas vers&amp;#245;es de projeto para Mono e Visual Studio.&lt;br /&gt;
&lt;h2&gt;30/05/2008&lt;/h2&gt;
Comecei a entender mais a fundo o projeto. Para isto, estudei HLSL e aprendi as principais diferen&amp;#231;as entre as duas linguagens.&lt;br /&gt;Portei o projeto para o Visual Studio 2008. E fiz uma an&amp;#225;lise do que j&amp;#225; foi feito e do que ainda faltava fazer.&lt;br /&gt;Acrescentei as &amp;quot;System-value semantics&amp;quot; &amp;#224; gramatica. Estas sem&amp;#226;nticas est&amp;#227;o dispon&amp;#237;veis apenas no &lt;a href="http://msdn.microsoft.com/en-us/library/bb509647(VS.85).aspx#System_Value" class="externalLink"&gt;Direct 3D 10&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;15/05/2008&lt;/h2&gt;O projeto &amp;#233; desenvolvido em C#. Como n&amp;#227;o conhecia a linguagem, aproveitei para aprender em um curso.&lt;br /&gt;&lt;br /&gt;Este curso faz parte do programa Students2Business, criado pela Microsoft e desenvolvido pelos Centros de Inova&amp;#231;&amp;#227;o e institui&amp;#231;&amp;#245;es de ensino parceiras. Resumidamente: o programa &amp;#233; gratu&amp;#237;to, o aluno pode escolher entre aulas de desenvolvimento ou de infra-estrutura de TI e &amp;#233; divido em 3 etapas. Ao final de cada etapa h&amp;#225; uma prova classificat&amp;#243;ria para a etapa seguinte. As etapas 2 e 3 possuem dura&amp;#231;&amp;#227;o de 40hs. Ao final da terceira etapa, os alunos que apresentarem os melhores projetos finais podem realizar gratuitamente provas de certifica&amp;#231;&amp;#227;o Microsoft e todos os alunos que concluirem as 3 etapas ter&amp;#227;o direito a participar do evento de formatura. Maiores informa&amp;#231;&amp;#245;es sobre o programa em &lt;a href="http://proform.msdnbrasil.tempsite.ws/public/Default.aspx" class="externalLink"&gt;http://proform.msdnbrasil.tempsite.ws/public/Default.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;30/04/2008&lt;/h2&gt;
Ol&amp;#225;!&lt;br /&gt;&lt;br /&gt;Me chamo B&amp;#225;rbara e entrei no projeto para substituir o Vitor, que se afastou para fazer doutorado. Como ele, vou utilizar este espa&amp;#231;o para periodicamente publicar os avan&amp;#231;os do projeto.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;21/03/2008&lt;/h2&gt;
Nesta semana terminei a separa&amp;#231;&amp;#227;o das fun&amp;#231;&amp;#245;es em arquivos diferentes e iniciei algumas convers&amp;#245;es de nomes de vari&amp;#225;veis de acordo com um contexto sem&amp;#226;ntico. &lt;br /&gt;&lt;br /&gt;Por exemplo, enquanto em HLSL temos: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void main(
        float4 position   : POSITION, 
        float3 normal      : NORMAL, 
	float2 uv : TEXCOORD0,
	float3 lightDir : TEXCOORD1,
	float3 eyeDir : TEXCOORD2,
	float3 spotDir : TEXCOORD3,
	float3 lightDir1 : TEXCOORD4,
	float3 spotDir1 : TEXCOORD5,
	float4 shadowUV1 : TEXCOORD6,
	float4 shadowUV2 : TEXCOORD7)
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Em GLSL teremos: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
varying vec3 tangentEyeDir;
varying vec3 tangentLightDir[2];
varying vec3 tangentSpotDir[2];
varying vec4 shadowUV[2]; 
void main() { ... }
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;uv, position e normal no HLSL seriam as vari&amp;#225;veis pr&amp;#233;-definidas gl_TexCoord[0], gl_Vertex e gl_Normal  no GLSL. &lt;br /&gt;
&lt;h2&gt;14/03/2008&lt;/h2&gt;
Nesta semana comecei a construir o separador de fun&amp;#231;&amp;#245;es. De um arquivo HLSL pode-se gerar v&amp;#225;rios GLSL. Para tal utilizo o grafo de depend&amp;#234;ncias das fun&amp;#231;&amp;#245;es declaradas no arquivo e em seus includes para separar as fun&amp;#231;&amp;#245;es corretamente, levando para o arquivo correto a formata&amp;#231;&amp;#227;o desejada e os coment&amp;#225;rios pertinentes a ela.  &lt;br /&gt;
&lt;h2&gt;07/03/2008&lt;/h2&gt;
Enquanto o HLSL permite v&amp;#225;rias entradas de execu&amp;#231;&amp;#227;o, ou seja, v&amp;#225;rias fun&amp;#231;&amp;#245;es main, o GLSL s&amp;#243; permite uma e exige o nome main. Desta forma, esta semana, trabalhei na cria&amp;#231;&amp;#227;o de um grafo de chamadas de fun&amp;#231;&amp;#245;es, para determinar quais fun&amp;#231;&amp;#245;es est&amp;#227;o sendo utilizadas para cada fun&amp;#231;&amp;#227;o de entrada no HLSL. Com esse grafo, poderei colocar cada fun&amp;#231;&amp;#227;o de entrada do HLSL em um arquivo diferente, levando tamb&amp;#233;m suas fun&amp;#231;&amp;#245;es dependentes. &lt;br /&gt;
&lt;h2&gt;29/02/2008&lt;/h2&gt;
Nesta semana trabalhei com a migra&amp;#231;&amp;#227;o da declara&amp;#231;&amp;#227;o de vari&amp;#225;veis uniform e varying, de uma fun&amp;#231;&amp;#227;o para o contexto do arquivo. &lt;br /&gt;&lt;br /&gt;Do HLSL:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void funcao(
    // parameters 
    float4 position,
    uniform float4 lightPosition, // object space 
    uniform float4x4 texViewProj2) {..}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para o GLSL &lt;br /&gt;&lt;pre&gt;
// parameters 
uniform float4 lightPosition; // object space 
uniform float4x4 texViewProj2;

void funcao(
     float4 position
) {..}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Migra&amp;#231;&amp;#227;o simples, mas trabalhosa quando se tem uma &amp;#225;rvore de Tokens sem ignorar espa&amp;#231;os, coment&amp;#225;rios, novas linhas e tabula&amp;#231;&amp;#245;es. Acabei tento muita dificuldade em identificar os coment&amp;#225;rios relevantes que deveriam ser movidos juntamente com o par&amp;#226;metro.&lt;br /&gt;
&lt;h2&gt;22/02/2008&lt;/h2&gt;
Ol&amp;#225; a todos. &lt;br /&gt;&lt;br /&gt;Neste espa&amp;#231;o vou publicar os avan&amp;#231;os do projeto semanalmente. &lt;br /&gt;&lt;br /&gt;Nesta &amp;#250;ltima semana testei a &lt;a href="http://OGRE" class="externalLink"&gt;http://www.ogre3d.org/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; como arquitetura para os testes do projeto. Ao converter shaders de HLSL para GLSL, &amp;#233; necess&amp;#225;rio tamb&amp;#233;m converter o c&amp;#243;digo fonte do programa que os usa, da API do DirectX para a da OpenGL. Esta parte n&amp;#227;o &amp;#233; coberta por este projeto, portanto &amp;#233; manual. &lt;br /&gt;&lt;br /&gt;A OGRE &amp;#233; uma engine que permite o uso de shaders HLSL, Cg e GLSL de maneira unificada, removendo os links diretos ao DirectX ou ao OpenGL. Usando-a, n&amp;#227;o perderemos tempo migrando o c&amp;#243;digo fonte dos testes, apenas com os testes dos shaders. &lt;br /&gt;&lt;br /&gt;Tamb&amp;#233;m desenvolvi uma parte do conversor: 
&lt;ol&gt;&lt;li&gt;A troca da fun&amp;#231;&amp;#227;o &amp;quot;mul&amp;quot; pelo &amp;quot;*&amp;quot;&lt;/li&gt;
&lt;li&gt;A invers&amp;#227;o de par&amp;#226;metros na fun&amp;#231;&amp;#227;o &amp;quot;cross&amp;quot;&lt;/li&gt;
&lt;li&gt;A remo&amp;#231;&amp;#227;o de par&amp;#226;metros na fun&amp;#231;&amp;#227;o &amp;quot;main&amp;quot;&lt;/li&gt;&lt;/ol&gt;
&lt;br /&gt;E estudei algumas propriedades da representa&amp;#231;&amp;#227;o de matrizes das duas linguagens. Apesar dos elementos descritos na p&amp;#225;gina &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Differences%20Between%20HLSL%20and%20GLSL&amp;referringTitle=Blog"&gt;Differences Between HLSL and GLSL&lt;/a&gt;, ainda tenho d&amp;#250;vidas sobre o modo de trabalho com as matrizes, especialmente se devo ou n&amp;#227;o transp&amp;#244;-las.  &lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Fri, 06 Nov 2009 16:06:07 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Blog 20091106040607P</guid></item><item><title>Updated Wiki: Blog</title><link>http://hl2glsl.codeplex.com/wikipage?title=Blog&amp;version=63</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Blog do Projeto&lt;/h1&gt;
Unfortunately this page exists only in portuguese. &lt;br /&gt;
&lt;h2&gt;03/11/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estive bastante envolvido com as tarefas acad&amp;#234;micas nos &amp;#250;ltimos dias, assim que n&amp;#227;o tenho tido muito tempo de postar aqui os resultados do meu trabalho.&lt;br /&gt;Encontrei um material muito bom sobre OpenCl aqui: &lt;a href="http://www.macresearch.org/opencl" class="externalLink"&gt;http://www.macresearch.org/opencl&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;, e assisti a todas as apresenta&amp;#231;&amp;#245;es. Nelas s&amp;#227;o apresentados desde quest&amp;#245;es gerais sobre opencl at&amp;#233; otimiza&amp;#231;&amp;#245;es diversas. Vale a pena conferir.&lt;br /&gt;At&amp;#233;,&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;05/10/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;gostaria de fazer aqui um pequeno post apenas para comentar sobre um benchmark que foi feito pela SiSoftware (os respons&amp;#225;veis pelo famoso Sandra).&lt;br /&gt;O benchmark levou em considera&amp;#231;&amp;#227;o as vers&amp;#245;es 2.2 e 2.3 do driver da NVidia, comparando CUDA e Opencl. Os resultados completos podem ser conferidos aqui: &lt;a href="http://sisoftware.co.uk/index.html?dir=qa&amp;amp;location=gpu_opencl&amp;amp;langx=en&amp;amp;a=" class="externalLink"&gt;http://sisoftware.co.uk/index.html?dir=qa&amp;amp;location=gpu_opencl&amp;amp;langx=en&amp;amp;a=&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;A id&amp;#233;ia central &amp;#233; que o OpenCl est&amp;#225; praticamente &amp;#224; altura do CUDA (tendo em vista os testes desse benchmark) em termos de desempenho, o que responde a uma grande cr&amp;#237;tica ao OpenCL.&lt;br /&gt;&lt;br /&gt;Att,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;02/10/09&lt;/h2&gt;Bom dia,&lt;br /&gt;estou postando aqui hoje meu primeiro tutorial sobre OpenCL. Esse primeiro tutorial pretende ser uma inicia&amp;#231;&amp;#227;o, um hello world detalhado de como funciona uma aplica&amp;#231;&amp;#227;o OpenCl.&lt;br /&gt;Futuros tutoriais aprofundar-se-&amp;#227;o em outros temas;&lt;br /&gt;O tutorial pode ser encontrado aqui: &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=OpenCl%20Tutorials%20-%201&amp;referringTitle=Blog"&gt;OpenCl Tutorials - 1&lt;/a&gt;;&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;30/09/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;queria avisar que a nvidia liberou para a comunidade em geral o driver da vers&amp;#227;o 1.0 do OpenCL nesta segunda feira.&lt;br /&gt;A p&amp;#225;gina com informa&amp;#231;&amp;#245;es para download tanto de windows, linux e mac pode ser encontrada aqui: &lt;a href="http://www.nvidia.com/object/cuda_opencl.html" class="externalLink"&gt;http://www.nvidia.com/object/cuda_opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/09/09&lt;/h2&gt;Bom dia,&lt;br /&gt;Nessa &amp;#250;ltima semana fiz uma pequena apresenta&amp;#231;&amp;#227;o sobre o projeto, apresentando todas as suas fases. Disponibilizo aqui apresenta&amp;#231;&amp;#227;o com &amp;#225;udio &lt;a href="http://www.inf.ufrgs.br/~lpchatain/apresentacao_chatain.pptx" class="externalLink"&gt;http://www.inf.ufrgs.br/~lpchatain/apresentacao_chatain.pptx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;(~14mb) (o Microsoft Office 2007 &amp;#233; necess&amp;#225;rio para abrir a apresenta&amp;#231;&amp;#227;o, um plugin de compatibilidade para vers&amp;#245;es anteriores do Office pode ser encontrada aqui: &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=941b3470-3ae9-4aee-8f43-c6bb74cd1466&amp;amp;displaylang=en" class="externalLink"&gt;http://www.microsoft.com/downloads/details.aspx?familyid=941b3470-3ae9-4aee-8f43-c6bb74cd1466&amp;amp;displaylang=en&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;);&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;14/09/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;nesta &amp;#250;ltima semana estive tentando fazer um benchmark do Cuda. Trata-se de um programa que resolve o problema das n-rainhas*, desenvolvido em Cuda e C&lt;u&gt;&lt;/u&gt;. O trabalho em quest&amp;#227;o foi feito pelo Vitor, e pode ser conferido em &lt;a href="http://vitorpamplona.com/wiki/An%C3%A1lise%20de%20Performance:%20C%20vs%20Cuda" class="externalLink"&gt;http://vitorpamplona.com/wiki/An%C3%A1lise%20de%20Performance:%20C%20vs%20Cuda&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;Nesse trabalho foi concluido que a implementa&amp;#231;&amp;#227;o em C&lt;u&gt;&lt;/u&gt; estava mais eficiente que a em Cuda. Entretanto fora utilizada a vers&amp;#227;o 1.0 do Cuda, e minha inten&amp;#231;&amp;#227;o era fazer um novo teste com a nova vers&amp;#227;o do compilador, para verificar eventuais melhorias de performance. Tamb&amp;#233;m gostaria de fazer os testes com diferentes configura&amp;#231;&amp;#245;es de hardware.&lt;br /&gt;Entretanto estive com bastantes dificuldades em fazer os testes funcionarem. Eles apresentaram um comportamento an&amp;#244;malo (leia-se imprevis&amp;#237;vel) na m&amp;#225;quina em que iniciei os testes, e atribui o problema &amp;#224; arquitetura 64bits da nova m&amp;#225;quina. Mudando para um processador 32 bits n&amp;#227;o tenho problemas com a compila&amp;#231;&amp;#227;o, entretanto estou tendo problemas com os kernels, que falham em sua execu&amp;#231;ao. Acredito ser um pequeno problema com a mudan&amp;#231;a do compilador (1.0 -&amp;gt; 2.2), mas ainda n&amp;#227;o consegui identific&amp;#225;-lo.&lt;br /&gt;Estarei postando aqui em breve um relat&amp;#243;rio de meus testes.&lt;br /&gt;&lt;br /&gt;Fora isso continuo estudando OpenCl, o que &amp;#233; bastante parecido com Cuda, assim que vou 'com as duas ao mesmo tempo'.&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;28/08/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estive estudando uma maneira de gerenciar automaticamente a inclus&amp;#227;o da DLL (como citado no post anterior). Postei algumas perguntas no blog da MSDN e obtive algumas respostas interessantes, que devem ser testadas nos proximos dias.&lt;br /&gt;&lt;br /&gt;Estive tamb&amp;#233;m estudando nessas &amp;#250;ltimas semanas &lt;b&gt;OpenCl&lt;/b&gt;.&lt;br /&gt;OpenCl &amp;#233; uma linguagem inicialmente criada pela Apple - e que teve como colaboradores a Intel, a nVidia e a AMD - para escrever programas que executem em ambientes heterogeneos, compostos de GPUs e CPUs.&lt;br /&gt;A linguagem foi 'abra&amp;#231;ada' pelo Kronos Group, que disponibilizou recentemente a especifica&amp;#231;&amp;#227;o da vers&amp;#227;o 1.0.&lt;br /&gt;Atualmente existem apenas vers&amp;#245;es beta dos drivers (visto que o kronos group somente disponibiliza a especifica&amp;#231;&amp;#227;o, cabe &amp;#224;s fabricantes de hardware gr&amp;#225;fico implementarem essa especifica&amp;#231;&amp;#227;o e fornecerem um compilador e um driver/sdk.&lt;br /&gt;&lt;br /&gt;Eu estou aqui testando com o driver beta da nvidia (apenas para desenvolvedores registrados). A implementa&amp;#231;&amp;#227;o da nVidia nada mais &amp;#233; que um 'mapeamento' da arquitetura CUDA para o OpenCl (creio que isso seja pr&amp;#243;ximo ao que a AMD/ATI est&amp;#225; fazendo, mapeando n&amp;#227;o para o CUDA mas para o Stream).&lt;br /&gt;&lt;br /&gt;Em CUDA, as fun&amp;#231;&amp;#245;es que se utilizam do paralelismo da GPU s&amp;#227;o conhecidas como &lt;i&gt;kernels&lt;/i&gt;.&lt;br /&gt;Kernels s&amp;#227;o executados por Streaming Multiprocessors (SMs). Cada SM, por sua vez, &amp;#233; composto por 8 Scalar Processors (SPs), os quais podem, cada um, executar simultaneamente at&amp;#233; 4 threads. Assim temos que um Streaming Multiprocessor pode executar simultaneamente at&amp;#233; 32 threads, o que chamaremos de &lt;i&gt;warp&lt;/i&gt;.&lt;br /&gt;Sempre que invocamos um kernel, especificamos para ele quantos &lt;i&gt;thread&lt;/i&gt; &lt;i&gt;blocks&lt;/i&gt; e quantas &lt;i&gt;threads&lt;/i&gt; &lt;i&gt;per&lt;/i&gt; &lt;i&gt;block&lt;/i&gt; queremos que esse kernel utilize. Cada SM encarrega-se da execu&amp;#231;&amp;#227;o de 1 thread block.&lt;br /&gt;Teoricamente, assim, se tivermos menos que 32 threads em um thread block estaremos 'perdendo processamento', pois n&amp;#227;o teremos preenchido o warp do SM. Se tivermos mais que 32 threads per block, entretanto, nossa situa&amp;#231;&amp;#227;o depender&amp;#225; da quantidade de mem&amp;#243;ria e de registradores que estar&amp;#227;o sendo utilizados. Funciona da seguinte forma: a CPU utiliza cache para esconder a latencia de mem&amp;#243;ria, i.e. para n&amp;#227;o termos que esperar sempre que os dados cheguem, n&amp;#243;s armazenamos-nos em uma cache. Na GPU escondemos a lat&amp;#234;ncia da mem&amp;#243;ria com computa&amp;#231;&amp;#245;es. Temos que a troca de contexto entre threads &amp;#233; muito veloz, assim ao inv&amp;#233;s de armazenarmos a mem&amp;#243;ria em uma grande cache, simplesmente mandamos outra thread executar enquanto esperamos, contanto que haja registradores livres no banco de registradores do SM.&lt;br /&gt;&lt;br /&gt;Em OpenCl temos a no&amp;#231;&amp;#227;o de &lt;i&gt;work-item&lt;/i&gt;s, que s&amp;#227;o mapeados para CUDA Threads, temos a no&amp;#231;&amp;#227;o de &lt;i&gt;work-groups&lt;/i&gt;, que s&amp;#227;o mapeados para thread blocks e por fim temos um NDRange, que &amp;#233; mapeado para um grid de thread blocks.&lt;br /&gt;O mapeamento &amp;#233; feito compilando OpenCl para o mesmo &amp;quot;bytecode&amp;quot;: PTX.&lt;br /&gt;&lt;br /&gt;Em breve estarei postando aqui trechos iniciais de c&amp;#243;digo em OpenCl, e espero estar fazendo alguns benchmarks com CUDA/OpenCl/CPU.&lt;br /&gt;&lt;br /&gt;Para maiores informa&amp;#231;&amp;#245;es a respeito das duas linguagens:
&lt;ul&gt;&lt;li&gt;Cuda:
&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.nvidia.com/object/cuda_home.html#" class="externalLink"&gt;http://www.nvidia.com/object/cuda_home.html#&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/CUDA" class="externalLink"&gt;http://en.wikipedia.org/wiki/CUDA&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ddj.com/hpc-high-performance-computing/207200659" class="externalLink"&gt;http://www.ddj.com/hpc-high-performance-computing/207200659&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;OpenCl
&lt;ul&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/OpenCL" class="externalLink"&gt;http://en.wikipedia.org/wiki/OpenCL&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.khronos.org/opencl/" class="externalLink"&gt;http://www.khronos.org/opencl/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.nvidia.com/object/cuda_opencl.html" class="externalLink"&gt;http://www.nvidia.com/object/cuda_opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ati.amd.com/technology/streamcomputing/opencl.html" class="externalLink"&gt;http://ati.amd.com/technology/streamcomputing/opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.openclworld.com/" class="externalLink"&gt;http://www.openclworld.com/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/07/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;Nesta semana estive com alguns problemas relativos &amp;#224; compatibilidade do debugger quando o projeto &amp;#233; levado a outros computadores. Esses problemas se deveram n&amp;#227;o &amp;#224; falta de compatibilidade do programa, mas sim do Package. Corrigi o problema, mas pretendo investigar a sua causa.&lt;br /&gt;Estou agora precisando ter acesso ao executavel gerado ap&amp;#243;s a compila&amp;#231;&amp;#227;o, estive dando uma olhada nisso nesta semana, sem muito sucesso. Al&amp;#233;m disso, preciso encontrar uma forma de manter sempre a DLL modificada como a acessivel pelo programa, ou seja, preciso de alguma forma manter a dll nas pastas do Visual Studio, no local onde o Package &amp;#233; instalado, e fazer com que tudo isso se ajeite na hora da instala&amp;#231;&amp;#227;o do pacote.&lt;br /&gt;Al&amp;#233;m desses pequenos problemas, continuo trabalhando na parte gr&amp;#225;fica (infelizmente n&amp;#227;o sou muito proficiente na cria&amp;#231;&amp;#227;o de interfaces amig&amp;#225;veis e bonitas) para integr&amp;#225;-la bem ao ambiente do Visual Studio. Ainda estou pensando em uma boa forma de dispor os compontentes, e em como melhorar a usabilidade do debugger.&lt;br /&gt;Fora isso ele se encontra bem integrado. &amp;#201; preciso fazer alguns testes, nos quais me dedicarei na pr&amp;#243;xima semana.&lt;br /&gt;&lt;br /&gt;At&amp;#233; la,&lt;br /&gt;&lt;br /&gt;Leonardo&lt;br /&gt;
&lt;h2&gt;08/07/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;Estou fazendo atualmente alguns ajustes automatizar mais o debugger, utilizando para isso as interface IVsRunningDocTableEvents, que implementa alguns m&amp;#233;todos para obter as notifica&amp;#231;&amp;#245;es sobre modifica&amp;#231;&amp;#245;es na IDE.&lt;br /&gt;Para poder passar a receber os eventos da IDE (que ser&amp;#227;o tratados pelos handlers da interface, a saber:
&lt;ul&gt;&lt;li&gt;int IVsRunningDocTableEvents.OnAfterAttributeChange&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterDocumentWindowHide&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterFirstDocumentLock&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterSave&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnBeforeDocumentWindowShow&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnBeforeLastDocumentUnlock&lt;/li&gt;&lt;/ul&gt;
)&lt;br /&gt;&lt;br /&gt;Esses eventos s&amp;#227;o importantes para que possamos ser notificados de modifica&amp;#231;&amp;#245;es importantes, como por exemplo saber quais s&amp;#227;o os documentos que est&amp;#227;o abertos.&lt;br /&gt;&lt;br /&gt;Para poder receber os eventos, devemos nos inscrever da seguinte forma:&lt;br /&gt;Declaramos inicialmente um cookie:
&lt;ul&gt;&lt;li&gt;uint cookie;&lt;/li&gt;&lt;/ul&gt;
E logo ap&amp;#243;s devemos declarar uma interface IVsRunningDocumentTable, e solicitar que ela avise sobre os eventos
&lt;ul&gt;&lt;li&gt;IVsRunningDocumentTable rdt = &lt;/li&gt;&lt;/ul&gt;
                (IVsRunningDocumentTable)Package.GetGlobalService(typeof(SVsRunningDocumentTable));
&lt;ul&gt;&lt;li&gt;rdt.AdviseRunningDocTableEvents(this, out dwCookie);&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Em breve, novas novidades.&lt;br /&gt;At&amp;#233;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;11/06/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;infelizemente, ap&amp;#243;s algum tempo de estudo em cima do debugger de exemplo, feito por Jackson Davis, dispon&amp;#237;vel em &lt;a href="http://code.msdn.microsoft.com/debugenginesample" class="externalLink"&gt;http://code.msdn.microsoft.com/debugenginesample&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;, e ap&amp;#243;s uma troca de e-mails com o mesmo, constatei que o desenvolvimento de uma debug engine para o VS, ou seja, o objetivo inicial de integrar totalmente o debugger de GLSL com o debugger do Visual Studio &amp;#233; demasiado complexa, visto que h&amp;#225; um grande n&amp;#250;mero de interfaces a implementar e que aparentemente o debugger de GLSL n&amp;#227;o &amp;#233; compat&amp;#237;vel com o modelo de debug engine que o Visual Studio espera. Com certeza ha uma maneira de realizar essa integra&amp;#231;ao, fazendo as devidas modifica&amp;#231;&amp;#245;es no debugger e implementando as interfaces requeridas pelo VS, mas esse trabalho levar&amp;#225; muito tempo.&lt;br /&gt;Portanto, dadas as condi&amp;#231;&amp;#245;es, optamos por desenvolver o depurador de forma externa ao depurador do Visual Studio, como j&amp;#225; vinha sendo feito em paralelo. Existe uma quantidade consideravel de melhorias que se podem fazer e &amp;#233; esse o atual objetivo.&lt;br /&gt;Tendo em vista o atual foco do trabalho, em pouco tempo espero estar postando alguns print screens e releases do debugger 'integrado'.&lt;br /&gt;&lt;br /&gt;Obrigado,&lt;br /&gt;&lt;br /&gt;Leonardo&lt;br /&gt;
&lt;h2&gt;26/05/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estou utilizando os objetos DTE e DTE2 para alguns testes. Ainda tive alguns problemas ap&amp;#243;s o &amp;#250;ltimo post para conseguir o objeto, mas agora essa j&amp;#225; &amp;#233; uma quest&amp;#227;o do passado.&lt;br /&gt;Estive nessas semanas estudando os objetos DTE e DTE2 e tamb&amp;#233;m estudando um projeto de exemplo de um depurador C&lt;u&gt;&lt;/u&gt; integrado ao Visual Studio. Os resultados desse estudo ainda n&amp;#227;o s&amp;#227;o vis&amp;#237;veis no depurador GLSL.&lt;br /&gt;Quanto a altera&amp;#231;oes no depurador, coloquei uma lista com os shaders sendo editados no projeto, de forma que o usu&amp;#225;rio possa escolher mais facilmente qual o shader a ser escolhido. Vou seguir com algumas altera&amp;#231;&amp;#245;es visuais desse estilo para deixar o debugger mais amig&amp;#225;vel.&lt;br /&gt;&lt;br /&gt;At&amp;#233;&lt;br /&gt;
&lt;h2&gt;12/05/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;ontem descobri uma solu&amp;#231;&amp;#227;o interessante para um pequeno problema que me atormentou por bastante tempo e que pelo visto atormenta bastante gente ainda.&lt;br /&gt;Para solucionar uma s&amp;#233;rie de quest&amp;#245;es ao desenvolver VSPackages, podemos utilizar o &amp;quot;automation object&amp;quot; DTE, que representa o objeto de mais alta hierarquia no ambiente EnvDTE, que possui referencias a todos os elementos da automa&amp;#231;&amp;#227;o do n&amp;#250;cleo do VS. Para tanto declaramos uma interface DTE, pertencente ao namespace EnvDTE (&amp;#233; necess&amp;#225;rio adicionar uma Reference ao projeto: EnvDTE), e utilizamos o m&amp;#233;todo GetService para recuperar o objeto DTE (ele ser&amp;#225; referenciado pela interface DTE que declaramos).&lt;br /&gt;Pretendo colocar mais explica&amp;#231;&amp;#245;es sobre o objeto DTE nos proximos post, mas agora quero me concentrar na explica&amp;#231;&amp;#227;o e solu&amp;#231;&amp;#227;o do problema que me atormentou.&lt;br /&gt;Eis que o seguinte c&amp;#243;digo &amp;#233; o respons&amp;#225;vel por declarar e recuperar o objeto DTE:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; EnvDTE;

DTE dte;

&lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Initialize() {
&lt;span style="color:Green;"&gt;//Inicializa&amp;#231;&amp;#245;es&lt;/span&gt;

&lt;span style="color:Blue;"&gt;this&lt;/span&gt;.dte = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SDTE)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; DTE;
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Entretanto, ap&amp;#243;s a execu&amp;#231;&amp;#227;o do trecho, dte continuava sempre com valor null, o que acabava gerando exce&amp;#231;&amp;#245;es e obviamente n&amp;#227;o era o que deveria estar acontecendo.&lt;br /&gt;Buscando na internet, encontrei no VSX Team Blog (o blog do pessoal do VSX (Visual Studio Extensibility)) a solu&amp;#231;&amp;#227;o para meu problema.&lt;br /&gt;O fato &amp;#233; que caso o ambiente n&amp;#227;o esteja totalmente carregado (em &amp;quot;zombie state&amp;quot;), a solicita&amp;#231;&amp;#227;o da referencia do objeto DTE retorna null. Como eu queria que o package fosse carregado juntamente com o VS (no startup), a inicializa&amp;#231;&amp;#227;o do package ocorria antes de o ambiente estar totalmente carregado, e dte continha sempre o valor null.&lt;br /&gt;Assim, a solu&amp;#231;&amp;#227;o proposta pelo pessoal do blog &amp;#233; a seguinte: utilizar a interface IVsShellPropertyEvents, implementando o handler OnShellPropertyChange, o qual faz o tracking do estado da IDE. A propriedade que diz se o VS est&amp;#225; zombie &amp;#233; a VSPROPID_Zombie.&lt;br /&gt;Segue abaixo a implementa&amp;#231;&amp;#227;o do blog do pessoal do VSX:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
      DTE dte;
      &lt;span style="color:Blue;"&gt;uint&lt;/span&gt; cookie;
      &lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Initialize()
      {
           &lt;span style="color:Blue;"&gt;base&lt;/span&gt;.Initialize();
           IVsShell shellService = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsShell)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; IVsShell;
           &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (shellService != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
                ErrorHandler.ThrowOnFailure(shellService.AdviseShellPropertyChanges(&lt;span style="color:Blue;"&gt;this&lt;/span&gt;,&lt;span style="color:Blue;"&gt;out&lt;/span&gt; cookie));
           ...
        }

        &lt;span style="color:Blue;"&gt;#region&lt;/span&gt; IVsShellPropertyEvents Members

        &lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;int&lt;/span&gt; OnShellPropertyChange(&lt;span style="color:Blue;"&gt;int&lt;/span&gt; propid, &lt;span style="color:Blue;"&gt;object&lt;/span&gt; &lt;span style="color:Blue;"&gt;var&lt;/span&gt;)
        {
            &lt;span style="color:Green;"&gt;// when zombie state changes to false, finish package initialization&lt;/span&gt;
            &lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((&lt;span style="color:Blue;"&gt;int&lt;/span&gt;)__VSSPROPID.VSSPROPID_Zombie == propid)
            {
                &lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((&lt;span style="color:Blue;"&gt;bool&lt;/span&gt;)&lt;span style="color:Blue;"&gt;var&lt;/span&gt; == &lt;span style="color:Blue;"&gt;false&lt;/span&gt;)
                {
                    &lt;span style="color:Green;"&gt;// zombie state dependent code&lt;/span&gt;
                    &lt;span style="color:Blue;"&gt;this&lt;/span&gt;.dte = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SDTE)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; DTE;
                    &lt;span style="color:Green;"&gt;// eventlistener no longer needed&lt;/span&gt;
                    IVsShell shellService = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsShell)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; IVsShell;
                    &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (shellService != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
                        ErrorHandler.ThrowOnFailure(shellService.UnadviseShellPropertyChanges(&lt;span style="color:Blue;"&gt;this&lt;/span&gt;.cookie));
                    &lt;span style="color:Blue;"&gt;this&lt;/span&gt;.cookie = 0;
                }
            }

            &lt;span style="color:Blue;"&gt;return&lt;/span&gt; VSConstants.S_OK;

        }

        &lt;span style="color:Blue;"&gt;#endregion&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Esse artigo pode ser encontrado em &lt;a href="http://blogs.msdn.com/vsxteam/archive/2008/06/09/dr-ex-why-does-getservice-typeof-envdte-dte-return-null.aspx" class="externalLink"&gt;http://blogs.msdn.com/vsxteam/archive/2008/06/09/dr-ex-why-does-getservice-typeof-envdte-dte-return-null.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Nos proximos posts estarei descrevendo mais a fundo a parte t&amp;#233;cnica do VS que estudei at&amp;#233; agora, e introduzirei alguns dos problemas futuros que pretendo estar resolvendo.&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;06/05/09&lt;/h2&gt;Ol&amp;#225;,&lt;br /&gt;nestas ultimas semanas estive um pouco sobrecarregado, e n&amp;#227;o tive muito tempo para escrever no blog. A primeira etapa da depura&amp;#231;&amp;#227;o j&amp;#225; esta concluida, entretanto restam alguns bugs relativos ao depurador que devem ser resolvidos antes de ser lan&amp;#231;ado um release do plug-in.&lt;br /&gt;Venho trabalhando na parte mais profunda da integra&amp;#231;&amp;#227;o.&lt;br /&gt;Al&amp;#233;m da mera quest&amp;#227;o de mapear as funcionalidades do depurador para a IDE (que n&amp;#227;o &amp;#233; trivial), restam alguns problemas que surgem do fato de que algumas features existentes no VS n&amp;#227;o se encontram atualmente no depurador (como por exemplo a utiliza&amp;#231;&amp;#227;o de breakpoints). Essas funcionalidades dever&amp;#227;o ser implementadas em breve.&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/04/09&lt;/h2&gt;Oi,&lt;br /&gt;nesta semana finalizei uma primeira integra&amp;#231;&amp;#227;o. Neste primeiro est&amp;#225;gio temos, como j&amp;#225; foi dito, o depurador da B&amp;#225;rbara executando sobre o Visual Studio.&lt;br /&gt;H&amp;#225; ainda uma s&amp;#233;rie de melhorias que devem ser feitas sobre esta integra&amp;#231;&amp;#227;o:
&lt;ul&gt;&lt;li&gt;Melhorias na estrutura&amp;#231;&amp;#227;o e organiza&amp;#231;&amp;#227;o do c&amp;#243;digo;&lt;/li&gt;
&lt;li&gt;Remo&amp;#231;&amp;#227;o de alguns bugs;&lt;/li&gt;
&lt;li&gt;Melhor organiza&amp;#231;&amp;#227;o visual;&lt;/li&gt;&lt;/ul&gt;
At&amp;#233; o fim desta semana planejo ter uma vers&amp;#227;o utilizavel do depurador, melhor organizada visualmente, com algumas funcionalidades a mais (no que toca &amp;#224; integra&amp;#231;&amp;#227;o, por exemplo que o depurador saiba qual o shader que deve ser depurado automaticamente, assim como o programa opengl.&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;20/04/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estou tendo alguns problemas na integra&amp;#231;&amp;#227;o, que derivam diretamente de d&amp;#250;vidas com rela&amp;#231;&amp;#227;o ao depurador desenvolvido pela Barbara.&lt;br /&gt;A id&amp;#233;ia desta primeira integra&amp;#231;&amp;#227;o &amp;#233; bastante simples, uma simples adi&amp;#231;&amp;#227;o do depurador da barbara sobre o VS. A id&amp;#233;ia &amp;#233; que ap&amp;#243;s essa etapa seja construido incrementalmente o depurador integrado. Nesse ponto temos algumas dificuldades, como por exemplo que o depurador n&amp;#227;o suporta a coloca&amp;#231;&amp;#227;o de breakpoints, mas executa sempre passo a passo, de forma que n&amp;#227;o se pode definir de forma mais flexivel o fluxo do programa.&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;10/04/09&lt;/h2&gt;Ol&amp;#225;,&lt;br /&gt;nesta semana estive trabalhando na efetiva integra&amp;#231;&amp;#227;o do Depurador GLSL para o VS2008. A id&amp;#233;ia inicial inserir apenas o depurador de forma externa ao depurador do Visual Studio, o que &amp;#233; uma tarefa mais simples e deve ser terminada at&amp;#233; o final da semana. Nos proximos posts estarei publicando screenshots e maiores explica&amp;#231;&amp;#245;es sobre essa integra&amp;#231;&amp;#227;o. Esse trabalho tem a vantagem de que o depurador estar&amp;#225; rapidamente pronto para ser utilizado, entretanto ele n&amp;#227;o estara integrado com o depurador do Visual Studio. Para acess&amp;#225;-lo haver&amp;#227;o menus e janelas exclusivas que se encarregar&amp;#227;o de realizar todo o processo.&lt;br /&gt;Ap&amp;#243;s terminar essa primeira etapa de integra&amp;#231;&amp;#227;o, pretendo construir uma Debug Engine que se comunique com a SDM e torne o processo de depura&amp;#231;&amp;#227;o transparente ao usu&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;01/04/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;nas semanas anteriores eu estive estudando o desenvolvimento de VSPackages gen&amp;#233;ricos, como uma forma de me familiarizar com eles. Nesta semana, e nas que vir&amp;#227;o, me voltei efetivamente para o VSDebugger e como extend&amp;#234;-lo.&lt;br /&gt;&lt;br /&gt;Basicamente o debugger do visual studio &amp;#233; composto de tr&amp;#234;s partes:
&lt;ul&gt;&lt;li&gt;Interface com o usu&amp;#225;rio (UI), que permite, por exemplo, que sejam colocados breakpoints, que o codigo seja executado instru&amp;#231;&amp;#227;o a instru&amp;#231;&amp;#227;o, etc.&lt;/li&gt;
&lt;li&gt;SDM (Session Debug Manager), que &amp;#233; basicamente quem gerencia as Debug Engines. Pode ser visto como um multiplexador de Debug Engines, al&amp;#233;m de fazer a comunica&amp;#231;&amp;#227;o com a UI. A SDM &amp;#233; implementada pelo VS e n&amp;#227;o ser&amp;#225; alterada.&lt;/li&gt;
&lt;li&gt;Debug Engine (DE), que &amp;#233; o elemento que efetivamente faz a depura&amp;#231;&amp;#227;o do programa, e se comunica com a SDM. &amp;#201; aqui que ser&amp;#225; introduzido o depurador de GLSL.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Assim, teremos que construir uma DE que incorpore o depurador desenvolvido pela B&amp;#225;rbara. Para construir uma DE, s&amp;#227;o necess&amp;#225;rios alguns passos:
&lt;ul&gt;&lt;li&gt;Primeiro devemos registrar nossa DE no Visual Studio, permitindo que ele a reconhe&amp;#231;a e utilize;&lt;/li&gt;
&lt;li&gt;Nossa DE deve, quando solicitado pela SDM, &amp;quot;conectar-se&amp;quot; ao programa a ser depurado. Isso ocorre quando o usu&amp;#225;rio escolhe depurar o programa. Ocorre ent&amp;#227;o uma troca de mensagens entre a SDM e as DEs;&lt;/li&gt;
&lt;li&gt;Agora que nossa DE est&amp;#225; &amp;quot;conectada&amp;quot; ao programa efetivamente podemos nos concentrar em depurar o programa. Esta etapa consiste em:
&lt;ul&gt;&lt;li&gt;Controlar o fluxo de execu&amp;#231;&amp;#227;o, respeitando breakpoints e execu&amp;#231;&amp;#227;o step-by-step;&lt;/li&gt;
&lt;li&gt;Comunicar-se com a SDM, fazendo com que tanto o VS quanto o usu&amp;#225;rio tenham um feedback da depura&amp;#231;&amp;#227;o;&lt;/li&gt;
&lt;li&gt;Al&amp;#233;m disso temos que permitir:
&lt;ul&gt;&lt;li&gt;A cria&amp;#231;&amp;#227;o/dele&amp;#231;&amp;#227;o de breakpoints;&lt;/li&gt;
&lt;li&gt;A inser&amp;#231;&amp;#227;o de watches;&lt;/li&gt;
&lt;li&gt;A visualiza&amp;#231;&amp;#227;o da pilha de chamadas;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;A seguir devemos nos desconectar do programa e solicitar &amp;#224; SDM para que o mesmo seja terminado;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Neste momento estou estudando um pouco mais o trabalho da B&amp;#225;rbara. Minhas d&amp;#250;vidas se concentram em como exatamente integrar todo o sistema de debugging do Visual Studio ao depurador que j&amp;#225; foi desenvolvido. Nos pr&amp;#243;ximos posts procurarei explicar um pouco melhor o funcionamento do mecanismo de depura&amp;#231;&amp;#227;o do VS, al&amp;#233;m de tentar aproximar um pouco mais os dois debuggers.&lt;br /&gt;&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;25/03/09 - Hello World&lt;/h2&gt;Nesta semana continuei a estudar o desenvolvimento de um Package para o VS2008. O estudo foi dirigido basicamente aos procedimentos de cria&amp;#231;&amp;#227;o e ao funcionamento dos recursos gerados pelo wizard.&lt;br /&gt;&lt;br /&gt;Para iniciar o desenvolvimento de um VSPackage, ap&amp;#243;s baixar o SDK do Visual Studio, &amp;#233; utilizar o wizard de cria&amp;#231;&amp;#227;o de package, que se encarrega de gerar o c&amp;#243;digo base, deixando para n&amp;#243;s apenas o desenvolvimento do Package.&lt;br /&gt;Assim, ap&amp;#243;s definir o nome de nosso Package, somos perguntados a respeito de algumas coisas sobre o ele: a linguagem em que o desenvolveremos, se queremos uma Tool Window, um Menu Tool, etc.&lt;br /&gt;Para construir o Hello World utilizei C# e criei tanto uma Tool Window quanto um Menu Tool.&lt;br /&gt;Os resultados foram os seguintes:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Window&lt;/b&gt; &lt;b&gt;Tool:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63149" alt="windowTool.bmp" title="windowTool.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63150" alt="windowTool2.bmp" title="windowTool2.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo Fonte&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; okButton_Click(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, System.EventArgs e)
        {
            MessageBox.Show(&lt;span style="color:#A31515;"&gt;&amp;quot;Seu nome &amp;#233; &amp;quot;&lt;/span&gt; + nameBox.Text.ToString(), &lt;span style="color:#A31515;"&gt;&amp;quot;Seu nome&amp;quot;&lt;/span&gt;, MessageBoxButtons.OK);
        }

        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; limparButton_Click(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, System.EventArgs e)
        {
            nameBox.Text = &lt;span style="color:#A31515;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;;
        }

&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Command Tool:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63151" alt="cmdTool.bmp" title="cmdTool.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo fonte do command:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; MenuItemCallback(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, EventArgs e)
        {
            &lt;span style="color:Green;"&gt;// Show a Message Box to prove we were here&lt;/span&gt;
            IVsUIShell uiShell = (IVsUIShell)GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsUIShell));
            Guid clsid = Guid.Empty;
            &lt;span style="color:Blue;"&gt;int&lt;/span&gt; result;
            Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(uiShell.ShowMessageBox(
                       0,
                       &lt;span style="color:Blue;"&gt;ref&lt;/span&gt; clsid,
                       &lt;span style="color:#A31515;"&gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;,
                       &lt;span style="color:Blue;"&gt;string&lt;/span&gt;.Format(CultureInfo.CurrentCulture, &lt;span style="color:#A31515;"&gt;&amp;quot;Hello World - Este &amp;#233; um menuTool&amp;quot;&lt;/span&gt;),
                       &lt;span style="color:Blue;"&gt;string&lt;/span&gt;.Empty,
                       0,
                       OLEMSGBUTTON.OLEMSGBUTTON_OK,
                       OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST,
                       OLEMSGICON.OLEMSGICON_INFO,
                       0,        &lt;span style="color:Green;"&gt;// false&lt;/span&gt;
                       &lt;span style="color:Blue;"&gt;out&lt;/span&gt; result));
        }
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Nos proximos posts estarei explicando com mais detalhes o funcionamento desses elementos. Atualmente estou buscando algo mais proximo do debugger, assim que possivelmente nos proximos posts n&amp;#227;o estarei mais lidando com exemplos gen&amp;#233;ricos, mas com algo mais focado no debugger em si.&lt;br /&gt;Uma &amp;#243;tima refer&amp;#234;ncia (em ingles) &amp;#233; &lt;a href="http://learnvsxnow.codeplex.com/" class="externalLink"&gt;http://learnvsxnow.codeplex.com/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;17/03/09&lt;/h2&gt;Oi pessoal,&lt;br /&gt;sou o Leonardo e este &amp;#233; meu primeiro post aqui.&lt;br /&gt;Atualmente, como a Barbara comentou, estou estudando o desenvolvimento de um &amp;quot;plug-in&amp;quot; para o Visual Studio, que permita a integra&amp;#231;&amp;#227;o do trabalho dela com o ambiente de desenvolvimento, facilitando assim o trabalho de depura&amp;#231;&amp;#227;o.&lt;br /&gt;A id&amp;#233;ia &amp;#233; tornar o depurador natural ao usu&amp;#225;rio do VS.&lt;br /&gt;&lt;br /&gt;O desenvolvimento se far&amp;#225; a partir de VSPackages, que s&amp;#227;o a ferramenta de extensibilidade mas completa que a Microsoft prov&amp;#234; para o Visual Studio.&lt;br /&gt;&lt;br /&gt;Mais informa&amp;#231;&amp;#245;es sobre Visual Studio Extensibility, al&amp;#233;m do download dos SDKs do VS2005 e VS208, podem ser encontradas aqui: &lt;a href="http://msdn.microsoft.com/en-us/vsx/default.aspx" class="externalLink"&gt;http://msdn.microsoft.com/en-us/vsx/default.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; (Visual Studio Extensibility Developer Center).&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;08/03/2009&lt;/h2&gt;Nesta semana trabalhei corrigindo problemas na interface e procurei deixar o c&amp;#243;digo do depurador menos &amp;quot;duro&amp;quot;. Como por exemplo, poder abrir os arquivos em qualquer ordem e n&amp;#227;o primeiro um tipo de shader e depois o outro.&lt;br /&gt;
&lt;h2&gt;24/02/2009&lt;/h2&gt;Em virtude da troca de bolsistas, optamos por focar no desenvolvimento do plugin para o Visual Studio. Desta forma, o Leonardo est&amp;#225; estudando o desenvolvimento de plugins, enquanto eu estou arrumando o c&amp;#243;digo para que esta integra&amp;#231;&amp;#227;o possa ser feita.&lt;br /&gt;
&lt;h2&gt;18/02/2009&lt;/h2&gt;Fui aprovada para o Mestrado em Ci&amp;#234;ncia da Computa&amp;#231;&amp;#227;o - UFRGS, desta forma, a partir de mar&amp;#231;o estarei afastada do projeto. Quem ir&amp;#225; dar continuidade ao projeto &amp;#233; o aluno no quinto semestre de gradua&amp;#231;&amp;#227;o do curso de &lt;br /&gt;Ci&amp;#234;ncia da Computa&amp;#231;&amp;#227;o - UFRGS, Leonardo Chatain. Seja bem vindo, Leonardo!&lt;br /&gt;
&lt;h2&gt;18/01/2009&lt;/h2&gt;Como disse no &amp;#250;ltimo post, comecei a trabalhar na integra&amp;#231;&amp;#227;o da ferramenta com outras. &lt;br /&gt;A ferramenta com a qual estou fazendo integra&amp;#231;&amp;#227;o &amp;#233; a Shader Designer. A principal dificuldade encontrada at&amp;#233; o momento est&amp;#225; sendo portar o projeto da Shader Designer do Microsoft Visual Studio 2003 para o 2008 (ambiente em que foi desenvolvido o depurador). Estou tendo que re-escrever praticamente todo o c&amp;#243;digo. Al&amp;#233;m de que, o Shader Designer utiliza uma s&amp;#233;rie de c&amp;#243;digos fontes e de bibliotecas de terceiros (vide abaixo) que tamb&amp;#233;m est&amp;#227;o sendo portados. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digos Fontes de terceiros&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;a) 3DLabs GLSL Open Source Compiler &lt;br /&gt;&lt;br /&gt;b) Algumas fun&amp;#231;&amp;#245;es da &amp;quot;Matrix and Quaternion fAQ&amp;quot; &lt;br /&gt;&lt;br /&gt;c) AVI exporter &lt;br /&gt;&lt;br /&gt;d) GLEW Extensions manager.&lt;br /&gt;&lt;br /&gt;e) MeshMender da Nvidia&lt;br /&gt;&lt;br /&gt;f) DEV-IL&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Bibliotecas de terceiros&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;a) Compona's SyntaxBox. &lt;br /&gt;&lt;br /&gt;b) Flexporter&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;15/12/2008&lt;/h2&gt;Nestas &amp;#250;ltimas semanas escrevi e apresentei um trabalho acad&amp;#234;mico sobre o assunto. A apresenta&amp;#231;&amp;#227;o pode ser obtida &lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=51900';"&gt;aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Tamb&amp;#233;m foram acrescentadas novas funcionalidades:
&lt;ul&gt;&lt;li&gt;Permite ao usu&amp;#225;rio optar por depurar:
&lt;ul&gt;&lt;li&gt;Apenas o shader;&lt;/li&gt;
&lt;li&gt;Apenas o programa OpenGL hospedeiro;&lt;/li&gt;
&lt;li&gt;Ambos.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;ul&gt;&lt;li&gt;Permite visualizar o valor atualizado das vari&amp;#225;veis que j&amp;#225; foram depuradas&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Nas pr&amp;#243;ximas semanas, vou iniciar o estudo sobre desenvolvimento de plugins e come&amp;#231;ar a integra&amp;#231;&amp;#227;o da ferramenta.&lt;br /&gt;
&lt;h2&gt;30/11/2008&lt;/h2&gt;Como dito no post anterior, foram muitas as dificuldades encontradas na utiliza&amp;#231;&amp;#227;o de extens&amp;#245;es para captura de dados da placa gr&amp;#225;fica.&lt;br /&gt;Para que outras pessoas que necessitem utilizar estas extens&amp;#245;es n&amp;#227;o enfrentem o mesmo problema (principalmente pela falta de documenta&amp;#231;&amp;#227;o e de exemplos de uso), coloquei na p&amp;#225;gina &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Capturing%20Data%20From%20Graphics%20Hardware&amp;referringTitle=Blog"&gt;Capturing Data From Graphics Hardware&lt;/a&gt;, uma explica&amp;#231;&amp;#227;o das extens&amp;#245;es utilizadas com exemplos. &lt;br /&gt;&lt;br /&gt;O depurador foi aprimorado. Agora &amp;#233; poss&amp;#237;vel n&amp;#227;o apenas ver o resultado da vari&amp;#225;vel que est&amp;#225; sendo depurada, mas tamb&amp;#233;m das fun&amp;#231;&amp;#245;es pr&amp;#233;-definidas da OpenGL Al&amp;#233;m disto, foi escrito um trabalho acad&amp;#234;mico sobre o assunto, que ap&amp;#243;s sua apresenta&amp;#231;&amp;#227;o, tamb&amp;#233;m estar&amp;#225; dispon&amp;#237;vel aqui no CodePlex.&lt;br /&gt;&lt;br /&gt;Em breve tamb&amp;#233;m estarei disponibilizando um realease do depurador.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;30/10/2008 - Finishing the Debugger&lt;/h2&gt;Durante este m&amp;#234;s me foquei em terminar o depurador GLSL.&lt;br /&gt;Foram muitas as dificuldades encontradas, principalmente na utiliza&amp;#231;&amp;#227;o de extens&amp;#245;es para capturar a sa&amp;#237;da dos processadores de v&amp;#233;rtices e de fragmentos.&lt;br /&gt;Foram implementados 3 m&amp;#243;dulos:
&lt;ul&gt;&lt;li&gt;Wrapper OpenGL -&amp;gt; respons&amp;#225;vel por capturar as opera&amp;#231;&amp;#245;es OpenGL realizadas pelo programa OpenGL hospedeiro e inserir os c&amp;#243;digos necess&amp;#225;rios para depura&amp;#231;&amp;#227;o;&lt;/li&gt;
&lt;li&gt;Parser GLSL -&amp;gt; respons&amp;#225;vel por re-escrever o c&amp;#243;digo do shader GLSL de modo a inserir as vari&amp;#225;veis de depura&amp;#231;&amp;#227;o necess&amp;#225;rias&lt;/li&gt;
&lt;li&gt;Interfce Gr&amp;#225;fica -&amp;gt; respons&amp;#225;vel por interligar e utilizar os resultados obtidos nos demais m&amp;#243;dulos, al&amp;#233;m de, &amp;#233; claro, ser a interface com o usu&amp;#225;rio.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Este trabalho foi apresentado no &lt;a href="http://www.propesq.ufrgs.br/sic2008/index.htm" class="externalLink"&gt;XX Sal&amp;#227;o de IC - UFRGS&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. A apresenta&amp;#231;&amp;#227;o pode ser baixada &lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=47908';"&gt;aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Para as pr&amp;#243;ximas semanas pretendo continuar trabalhando no aprimoramento da ferramenta e escrever um documento mais detalhado sobre seu desenvolvimento.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;30/09/2008 - GLSL Debugger&lt;/h2&gt;
Passei algum tempo sem postar no blog. Durante este tempo estava trabalhando em uma nova etapa do projeto, o desenvolvimento de um plugin de depura&amp;#231;&amp;#227;o de GLSL para o Visual Studio. Maiores detalhes do andamento e da descri&amp;#231;&amp;#227;o desta etapa podem ser encontrados em &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=GLSL%20Debugger&amp;referringTitle=Blog"&gt;GLSL Debugger&lt;/a&gt;.&lt;br /&gt;
&lt;h2&gt;18/08/2008&lt;/h2&gt;GLSL n&amp;#227;o possui suporte &amp;#224; cast impl&amp;#237;cito (ex: vec4 color = 0.5;) assim, acrescentei o cast explicito (ex: vec4 color = vec4(0.5); )&lt;br /&gt;&lt;br /&gt;Continuei com os testes do programa. A principal dificuldade encontrada nos testes &amp;#233; a valida&amp;#231;&amp;#227;o. Por enquanto, o m&amp;#233;todo utilizado para os testes consiste em pegar um c&amp;#243;digo HLSL v&amp;#225;lido, converter e testar em um compilador GLSL se o c&amp;#243;digo gerado &amp;#233; v&amp;#225;lido ou n&amp;#227;o. Se n&amp;#227;o for, o programa &amp;#233; corrigido. Ou seja, por falta de uma BNF oficial da HLSL, nossos testes s&amp;#227;o baseados em exemplos. O que n&amp;#227;o &amp;#233; o ideal. A id&amp;#233;ia &amp;#233; que a pr&amp;#243;xima etapa de testes seja realizada comparando as imagens geradas. Ou seja, ser&amp;#227;o obtidas imagens executando o shader HLSL e estas ser&amp;#227;o comparadas com as imagens obtidas atrav&amp;#233;s da execu&amp;#231;&amp;#227;o do shader GLSL. A diferen&amp;#231;a entre estas imagens nos dir&amp;#225; o percentual de erro obtido na convers&amp;#227;o. &amp;#201; mais uma forma de validar o programa, por&amp;#233;m, o fato dos testes serem baseados em exemplos persiste. Para que este fator n&amp;#227;o seja t&amp;#227;o relevante, estamos utilizando uma gama variada de exemplos.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;04/08/2008&lt;/h2&gt;Como o programa estava dispon&amp;#237;vel apenas em vers&amp;#245;es de linha de comando, desenvolvi uma vers&amp;#227;o que apresenta uma interface gr&amp;#225;fica simplificada. Com esta interface, basta o usu&amp;#225;rio carregar o c&amp;#243;digo HLSL e clicar em converter. Os c&amp;#243;digos s&amp;#227;o exibidos lado &amp;#224; lado, facilitando a visualiza&amp;#231;&amp;#227;o pelo usu&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;Esta interface apresenta um limitante, que &amp;#233; o fato de ser compat&amp;#237;vel apenas com sistemas Windows. Por&amp;#233;m, em breve, pretendo desenvolver uma vers&amp;#227;o compat&amp;#237;vel com outros sistemas.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;24/07/2008&lt;/h2&gt;GLSL n&amp;#227;o apresenta suporte ao comando &amp;quot;Switch&amp;quot;. Desta forma, fiz uma fun&amp;#231;&amp;#227;o que substitui este comando por &amp;quot;If..else&amp;quot;.&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;        switch ( teste ) {
    			case 0: k++; return teste; 
    			case 1: return teste; 
    			case 2: t++; return teste; 
    			default: { 
    				teste++;
       			} 
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;      if (teste == 0) { k++; return teste; }
      else if (teste == 1) { return teste;}
      else if (teste == 2) { t++; return teste; }
      else { teste++;  }
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;GLSL n&amp;#227;o permite atribui&amp;#231;&amp;#245;es para elementos dos vetores, se estes vetores forem vari&amp;#225;veis to tipo &amp;quot;varying&amp;quot;. Ent&amp;#227;o, fiz uma fun&amp;#231;&amp;#227;o que cria uma vari&amp;#225;vel tempor&amp;#225;ria, efetua a atribui&amp;#231;&amp;#227;o e ent&amp;#227;o atribui o valor &amp;#224; vari&amp;#225;vel original.&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;  float4 MyShader( float2 Tex : TEXCOORD0 ) : COLOR0
{
    float4 Color;
    
    Color = float4(1.0,1.0,1.0,1.0);
    Color.a;
    Color.a = 0.1;
    Color.rgb = float3(0.5f);

    Tex.y = Tex.y + (sin(timeraslow)*0.01);
    Tex.x = Tex.x + (cos(timeraslow)*0.01);
    Color = tex2D( g_samSrcColor, Tex.xy);

    Color -= tex2D( g_samSrcColor, Tex.xy-0.001)*2.0f;
    Color += tex2D( g_samSrcColor, Tex.xy+0.001)*2.0f;
    Color.rgb = float3((Color.r+Color.g+Color.b)/3.0f);   	
   	
    return Color;
}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt; varying vec2 Tex;

void main( )
{
    vec4 Color;
    
    Color = vec4(1.0,1.0,1.0,1.0);
    Color.a;
    Color.a = 0.1;
    Color.rgb = vec3(0.5); //n&amp;#227;o necessita de vari&amp;#225;vel tempor&amp;#225;ria pois n&amp;#227;o &amp;#233; varying

    vec2 tempTex = Tex; //como Tex era varying foi criada uma vari&amp;#225;vel tempor&amp;#225;ria 

    tempTex.y = Tex.y + (sin(timeraslow)*0.01);
    Tex=tempTex;
    tempTex.x = Tex.x + (cos(timeraslow)*0.01);
    Tex=tempTex;
    Color = tex2D( g_samSrcColor, Tex.xy);

    Color -= tex2D( g_samSrcColor, Tex.xy-0.001)*2.0;
    Color += tex2D( g_samSrcColor, Tex.xy+0.001)*2.0;
    Color.rgb = vec3((Color.r+Color.g+Color.b)/3.0));   	
   	
    gl_FragColor = Color;
}
&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;09/07/2008&lt;/h2&gt;Acrescentei a convers&amp;#227;o das fun&amp;#231;&amp;#245;es intr&amp;#237;nsicas. Para as fun&amp;#231;&amp;#245;es intr&amp;#237;nsicas de HLSL que n&amp;#227;o s&amp;#227;o suportadas pela GLSL (vide &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Differences%20Between%20HLSL%20and%20GLSL&amp;referringTitle=Blog"&gt;Differences Between HLSL and GLSL&lt;/a&gt;), &amp;#233; emitida uma mensagem de aviso ao usu&amp;#225;rio.  GLSL tamb&amp;#233;m n&amp;#227;o suporta a letra 'f' ap&amp;#243;s um n&amp;#250;mero do tipo float (ex: 1.0f), ent&amp;#227;o, inseri uma fun&amp;#231;&amp;#227;o que remove este 'f' do n&amp;#250;mero. &lt;br /&gt;&lt;br /&gt;Iniciei tamb&amp;#233;m a fase de testes do programa. Para isto estou utilizando os shaders  &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Parsing%20Shaders&amp;referringTitle=Blog"&gt;Parsing Shaders&lt;/a&gt;. Ap&amp;#243;s converter, executo o arquivo gerado no software &lt;a href="http://www.opengl.org/sdk/tools/ShaderDesigner" class="externalLink"&gt;Shader Designer&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. Este software &amp;#233; um editor/compilador de GLSL. Assim, atrav&amp;#233;s de sua sa&amp;#237;da, posso verificar se o c&amp;#243;digo GLSL gerado &amp;#233; v&amp;#225;lido ou n&amp;#227;o e corrigir os problemas encontrados.&lt;br /&gt;&lt;br /&gt;A vers&amp;#227;o mais atual dos fontes do projeto encontra-se &lt;a href="http://www.codeplex.com/hl2glsl/SourceControl/ListDownloadableCommits.aspx" class="externalLink"&gt;dispon&amp;#237;vel&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;04/07/2008&lt;/h2&gt;Fiz algumas altera&amp;#231;&amp;#245;es na gram&amp;#225;tica e acrescentei novas fun&amp;#231;&amp;#245;es para tratar estas altera&amp;#231;&amp;#245;es.&lt;br /&gt;&lt;br /&gt;Altera&amp;#231;&amp;#245;es na gram&amp;#225;tica:&lt;br /&gt;*Reconhecimento do par&amp;#226;metro &amp;quot;: Register&amp;quot;;&lt;br /&gt;*Reconhecimento do par&amp;#226;metro &amp;quot;: Packoffset&amp;quot;;&lt;br /&gt;*Reconhecimento do operador un&amp;#225;rio &amp;quot;!&amp;quot;;&lt;br /&gt;*Reconhecimento do tipo &amp;quot;uint&amp;quot;.&lt;br /&gt;&lt;br /&gt;GLSL n&amp;#227;o apresenta suporte para acesso &amp;#224; registradores. Assim, os par&amp;#226;metros &amp;quot;register&amp;quot; e &amp;quot;packoffset&amp;quot; n&amp;#227;o podem ser utilizados. A medida adotada para solucionar este problema &amp;#233; avisar ao usu&amp;#225;rio deste fato e perguntar se ele deseja remover estes par&amp;#226;metros. Caso ele opte por n&amp;#227;o remover, um aviso de que o c&amp;#243;digo gerado ser&amp;#225; inconsistente &amp;#233; emitido.&lt;br /&gt;&lt;br /&gt;O caso do tipo &amp;quot;uint&amp;quot; &amp;#233; similar, pois tamb&amp;#233;m n&amp;#227;o &amp;#233; suportado pela GLSL. S&amp;#243; que ao inv&amp;#233;s de remover a vari&amp;#225;vel, a op&amp;#231;&amp;#227;o dada ao usu&amp;#225;rio &amp;#233; a de troc&amp;#225;-lo pelo tipo int. &lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;18/06/2008&lt;/h2&gt;Passei a utilizar o Source Code Client do CodePlex para disponibilizar o c&amp;#243;digo fonte.&lt;br /&gt;&lt;br /&gt;Acrescentei as fun&amp;#231;&amp;#245;es para tratar &amp;quot;return&amp;quot; e o tipo da fun&amp;#231;&amp;#227;o &amp;quot;main&amp;quot;.&lt;br /&gt;&lt;br /&gt;Em GLSL &amp;#233; necess&amp;#225;rio uma fun&amp;#231;&amp;#227;o void main() que &amp;#233; de onde iniciar&amp;#225; a execu&amp;#231;&amp;#227;o.  Em HLSL, isto n&amp;#227;o &amp;#233; necess&amp;#225;rio.&lt;br /&gt;Assim, &amp;#233; preciso substituir o nome da fun&amp;#231;&amp;#227;o em HLSL por &amp;quot;main&amp;quot; e o tipo da fun&amp;#231;&amp;#227;o por void. O tipo da fun&amp;#231;&amp;#227;o deve ser salvo pois ele ser&amp;#225; utilizado na sa&amp;#237;da da fun&amp;#231;&amp;#227;o.  &lt;br /&gt;&lt;br /&gt;Como a fun&amp;#231;&amp;#227;o em GLSL &amp;#233; do tipo void, ela n&amp;#227;o tem mais o &amp;quot;return&amp;quot;.  Sua sa&amp;#237;da vai ser determinada de acordo com o tipo e os par&amp;#226;metros sem&amp;#226;nticos da fun&amp;#231;&amp;#227;o original, &lt;br /&gt;&lt;br /&gt;Ex: &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;float4 pixelShader( float4 color):COLOR
{
          float4 teste =float4(0,1,0,0);
          float4 tes   = color + teste;

          return tes;
} &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;varying vec4 color;

void main() { 

	vec4 teste = vec4(0,1,0,0);
	vec4 tes   = color + teste;
	
	gl_FragColor = vec4(tes) ;  
} &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;02/06/2008&lt;/h2&gt;
Disponibilizei os fontes em desenvolvimento do projeto na sess&amp;#227;o Releases nas vers&amp;#245;es de projeto para Mono e Visual Studio.&lt;br /&gt;
&lt;h2&gt;30/05/2008&lt;/h2&gt;
Comecei a entender mais a fundo o projeto. Para isto, estudei HLSL e aprendi as principais diferen&amp;#231;as entre as duas linguagens.&lt;br /&gt;Portei o projeto para o Visual Studio 2008. E fiz uma an&amp;#225;lise do que j&amp;#225; foi feito e do que ainda faltava fazer.&lt;br /&gt;Acrescentei as &amp;quot;System-value semantics&amp;quot; &amp;#224; gramatica. Estas sem&amp;#226;nticas est&amp;#227;o dispon&amp;#237;veis apenas no &lt;a href="http://msdn.microsoft.com/en-us/library/bb509647(VS.85).aspx#System_Value" class="externalLink"&gt;Direct 3D 10&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;15/05/2008&lt;/h2&gt;O projeto &amp;#233; desenvolvido em C#. Como n&amp;#227;o conhecia a linguagem, aproveitei para aprender em um curso.&lt;br /&gt;&lt;br /&gt;Este curso faz parte do programa Students2Business, criado pela Microsoft e desenvolvido pelos Centros de Inova&amp;#231;&amp;#227;o e institui&amp;#231;&amp;#245;es de ensino parceiras. Resumidamente: o programa &amp;#233; gratu&amp;#237;to, o aluno pode escolher entre aulas de desenvolvimento ou de infra-estrutura de TI e &amp;#233; divido em 3 etapas. Ao final de cada etapa h&amp;#225; uma prova classificat&amp;#243;ria para a etapa seguinte. As etapas 2 e 3 possuem dura&amp;#231;&amp;#227;o de 40hs. Ao final da terceira etapa, os alunos que apresentarem os melhores projetos finais podem realizar gratuitamente provas de certifica&amp;#231;&amp;#227;o Microsoft e todos os alunos que concluirem as 3 etapas ter&amp;#227;o direito a participar do evento de formatura. Maiores informa&amp;#231;&amp;#245;es sobre o programa em &lt;a href="http://proform.msdnbrasil.tempsite.ws/public/Default.aspx" class="externalLink"&gt;http://proform.msdnbrasil.tempsite.ws/public/Default.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;30/04/2008&lt;/h2&gt;
Ol&amp;#225;!&lt;br /&gt;&lt;br /&gt;Me chamo B&amp;#225;rbara e entrei no projeto para substituir o Vitor, que se afastou para fazer doutorado. Como ele, vou utilizar este espa&amp;#231;o para periodicamente publicar os avan&amp;#231;os do projeto.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;21/03/2008&lt;/h2&gt;
Nesta semana terminei a separa&amp;#231;&amp;#227;o das fun&amp;#231;&amp;#245;es em arquivos diferentes e iniciei algumas convers&amp;#245;es de nomes de vari&amp;#225;veis de acordo com um contexto sem&amp;#226;ntico. &lt;br /&gt;&lt;br /&gt;Por exemplo, enquanto em HLSL temos: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void main(
        float4 position   : POSITION, 
        float3 normal      : NORMAL, 
	float2 uv : TEXCOORD0,
	float3 lightDir : TEXCOORD1,
	float3 eyeDir : TEXCOORD2,
	float3 spotDir : TEXCOORD3,
	float3 lightDir1 : TEXCOORD4,
	float3 spotDir1 : TEXCOORD5,
	float4 shadowUV1 : TEXCOORD6,
	float4 shadowUV2 : TEXCOORD7)
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Em GLSL teremos: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
varying vec3 tangentEyeDir;
varying vec3 tangentLightDir[2];
varying vec3 tangentSpotDir[2];
varying vec4 shadowUV[2]; 
void main() { ... }
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;uv, position e normal no HLSL seriam as vari&amp;#225;veis pr&amp;#233;-definidas gl_TexCoord[0], gl_Vertex e gl_Normal  no GLSL. &lt;br /&gt;
&lt;h2&gt;14/03/2008&lt;/h2&gt;
Nesta semana comecei a construir o separador de fun&amp;#231;&amp;#245;es. De um arquivo HLSL pode-se gerar v&amp;#225;rios GLSL. Para tal utilizo o grafo de depend&amp;#234;ncias das fun&amp;#231;&amp;#245;es declaradas no arquivo e em seus includes para separar as fun&amp;#231;&amp;#245;es corretamente, levando para o arquivo correto a formata&amp;#231;&amp;#227;o desejada e os coment&amp;#225;rios pertinentes a ela.  &lt;br /&gt;
&lt;h2&gt;07/03/2008&lt;/h2&gt;
Enquanto o HLSL permite v&amp;#225;rias entradas de execu&amp;#231;&amp;#227;o, ou seja, v&amp;#225;rias fun&amp;#231;&amp;#245;es main, o GLSL s&amp;#243; permite uma e exige o nome main. Desta forma, esta semana, trabalhei na cria&amp;#231;&amp;#227;o de um grafo de chamadas de fun&amp;#231;&amp;#245;es, para determinar quais fun&amp;#231;&amp;#245;es est&amp;#227;o sendo utilizadas para cada fun&amp;#231;&amp;#227;o de entrada no HLSL. Com esse grafo, poderei colocar cada fun&amp;#231;&amp;#227;o de entrada do HLSL em um arquivo diferente, levando tamb&amp;#233;m suas fun&amp;#231;&amp;#245;es dependentes. &lt;br /&gt;
&lt;h2&gt;29/02/2008&lt;/h2&gt;
Nesta semana trabalhei com a migra&amp;#231;&amp;#227;o da declara&amp;#231;&amp;#227;o de vari&amp;#225;veis uniform e varying, de uma fun&amp;#231;&amp;#227;o para o contexto do arquivo. &lt;br /&gt;&lt;br /&gt;Do HLSL:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void funcao(
    // parameters 
    float4 position,
    uniform float4 lightPosition, // object space 
    uniform float4x4 texViewProj2) {..}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para o GLSL &lt;br /&gt;&lt;pre&gt;
// parameters 
uniform float4 lightPosition; // object space 
uniform float4x4 texViewProj2;

void funcao(
     float4 position
) {..}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Migra&amp;#231;&amp;#227;o simples, mas trabalhosa quando se tem uma &amp;#225;rvore de Tokens sem ignorar espa&amp;#231;os, coment&amp;#225;rios, novas linhas e tabula&amp;#231;&amp;#245;es. Acabei tento muita dificuldade em identificar os coment&amp;#225;rios relevantes que deveriam ser movidos juntamente com o par&amp;#226;metro.&lt;br /&gt;
&lt;h2&gt;22/02/2008&lt;/h2&gt;
Ol&amp;#225; a todos. &lt;br /&gt;&lt;br /&gt;Neste espa&amp;#231;o vou publicar os avan&amp;#231;os do projeto semanalmente. &lt;br /&gt;&lt;br /&gt;Nesta &amp;#250;ltima semana testei a &lt;a href="http://OGRE" class="externalLink"&gt;http://www.ogre3d.org/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; como arquitetura para os testes do projeto. Ao converter shaders de HLSL para GLSL, &amp;#233; necess&amp;#225;rio tamb&amp;#233;m converter o c&amp;#243;digo fonte do programa que os usa, da API do DirectX para a da OpenGL. Esta parte n&amp;#227;o &amp;#233; coberta por este projeto, portanto &amp;#233; manual. &lt;br /&gt;&lt;br /&gt;A OGRE &amp;#233; uma engine que permite o uso de shaders HLSL, Cg e GLSL de maneira unificada, removendo os links diretos ao DirectX ou ao OpenGL. Usando-a, n&amp;#227;o perderemos tempo migrando o c&amp;#243;digo fonte dos testes, apenas com os testes dos shaders. &lt;br /&gt;&lt;br /&gt;Tamb&amp;#233;m desenvolvi uma parte do conversor: 
&lt;ol&gt;&lt;li&gt;A troca da fun&amp;#231;&amp;#227;o &amp;quot;mul&amp;quot; pelo &amp;quot;*&amp;quot;&lt;/li&gt;
&lt;li&gt;A invers&amp;#227;o de par&amp;#226;metros na fun&amp;#231;&amp;#227;o &amp;quot;cross&amp;quot;&lt;/li&gt;
&lt;li&gt;A remo&amp;#231;&amp;#227;o de par&amp;#226;metros na fun&amp;#231;&amp;#227;o &amp;quot;main&amp;quot;&lt;/li&gt;&lt;/ol&gt;
&lt;br /&gt;E estudei algumas propriedades da representa&amp;#231;&amp;#227;o de matrizes das duas linguagens. Apesar dos elementos descritos na p&amp;#225;gina &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Differences%20Between%20HLSL%20and%20GLSL&amp;referringTitle=Blog"&gt;Differences Between HLSL and GLSL&lt;/a&gt;, ainda tenho d&amp;#250;vidas sobre o modo de trabalho com as matrizes, especialmente se devo ou n&amp;#227;o transp&amp;#244;-las.  &lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Thu, 05 Nov 2009 17:28:38 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Blog 20091105052838P</guid></item><item><title>Updated Wiki: Blog</title><link>http://hl2glsl.codeplex.com/wikipage?title=Blog&amp;version=62</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Blog do Projeto&lt;/h1&gt;
Unfortunately this page exists only in portuguese. &lt;br /&gt;
&lt;h2&gt;03/11/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estive bastante envolvido com as tarefas acad&amp;#234;micas nos &amp;#250;ltimos dias, assim que n&amp;#227;o tenho tido muito tempo de postar aqui os resultados do meu trabalho.&lt;br /&gt;Encontrei um material muito bom sobre OpenCl aqui: &lt;a href="http://www.macresearch.org/opencl" class="externalLink"&gt;http://www.macresearch.org/opencl&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;, e assisti a todas as apresenta&amp;#231;&amp;#245;es. Nelas s&amp;#227;o apresentados desde quest&amp;#245;es gerais sobre opencl at&amp;#233; otimiza&amp;#231;&amp;#227;o de mem&amp;#243;ria.&lt;br /&gt;Ate,&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;05/10/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;gostaria de fazer aqui um pequeno post apenas para comentar sobre um benchmark que foi feito pela SiSoftware (os respons&amp;#225;veis pelo famoso Sandra).&lt;br /&gt;O benchmark levou em considera&amp;#231;&amp;#227;o as vers&amp;#245;es 2.2 e 2.3 do driver da NVidia, comparando CUDA e Opencl. Os resultados completos podem ser conferidos aqui: &lt;a href="http://sisoftware.co.uk/index.html?dir=qa&amp;amp;location=gpu_opencl&amp;amp;langx=en&amp;amp;a=" class="externalLink"&gt;http://sisoftware.co.uk/index.html?dir=qa&amp;amp;location=gpu_opencl&amp;amp;langx=en&amp;amp;a=&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;A id&amp;#233;ia central &amp;#233; que o OpenCl est&amp;#225; praticamente &amp;#224; altura do CUDA (tendo em vista os testes desse benchmark) em termos de desempenho, o que responde a uma grande cr&amp;#237;tica ao OpenCL.&lt;br /&gt;&lt;br /&gt;Att,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;02/10/09&lt;/h2&gt;Bom dia,&lt;br /&gt;estou postando aqui hoje meu primeiro tutorial sobre OpenCL. Esse primeiro tutorial pretende ser uma inicia&amp;#231;&amp;#227;o, um hello world detalhado de como funciona uma aplica&amp;#231;&amp;#227;o OpenCl.&lt;br /&gt;Futuros tutoriais aprofundar-se-&amp;#227;o em outros temas;&lt;br /&gt;O tutorial pode ser encontrado aqui: &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=OpenCl%20Tutorials%20-%201&amp;referringTitle=Blog"&gt;OpenCl Tutorials - 1&lt;/a&gt;;&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;30/09/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;queria avisar que a nvidia liberou para a comunidade em geral o driver da vers&amp;#227;o 1.0 do OpenCL nesta segunda feira.&lt;br /&gt;A p&amp;#225;gina com informa&amp;#231;&amp;#245;es para download tanto de windows, linux e mac pode ser encontrada aqui: &lt;a href="http://www.nvidia.com/object/cuda_opencl.html" class="externalLink"&gt;http://www.nvidia.com/object/cuda_opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/09/09&lt;/h2&gt;Bom dia,&lt;br /&gt;Nessa &amp;#250;ltima semana fiz uma pequena apresenta&amp;#231;&amp;#227;o sobre o projeto, apresentando todas as suas fases. Disponibilizo aqui apresenta&amp;#231;&amp;#227;o com &amp;#225;udio &lt;a href="http://www.inf.ufrgs.br/~lpchatain/apresentacao_chatain.pptx" class="externalLink"&gt;http://www.inf.ufrgs.br/~lpchatain/apresentacao_chatain.pptx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;(~14mb) (o Microsoft Office 2007 &amp;#233; necess&amp;#225;rio para abrir a apresenta&amp;#231;&amp;#227;o, um plugin de compatibilidade para vers&amp;#245;es anteriores do Office pode ser encontrada aqui: &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=941b3470-3ae9-4aee-8f43-c6bb74cd1466&amp;amp;displaylang=en" class="externalLink"&gt;http://www.microsoft.com/downloads/details.aspx?familyid=941b3470-3ae9-4aee-8f43-c6bb74cd1466&amp;amp;displaylang=en&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;);&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;14/09/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;nesta &amp;#250;ltima semana estive tentando fazer um benchmark do Cuda. Trata-se de um programa que resolve o problema das n-rainhas*, desenvolvido em Cuda e C&lt;u&gt;&lt;/u&gt;. O trabalho em quest&amp;#227;o foi feito pelo Vitor, e pode ser conferido em &lt;a href="http://vitorpamplona.com/wiki/An%C3%A1lise%20de%20Performance:%20C%20vs%20Cuda" class="externalLink"&gt;http://vitorpamplona.com/wiki/An%C3%A1lise%20de%20Performance:%20C%20vs%20Cuda&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;Nesse trabalho foi concluido que a implementa&amp;#231;&amp;#227;o em C&lt;u&gt;&lt;/u&gt; estava mais eficiente que a em Cuda. Entretanto fora utilizada a vers&amp;#227;o 1.0 do Cuda, e minha inten&amp;#231;&amp;#227;o era fazer um novo teste com a nova vers&amp;#227;o do compilador, para verificar eventuais melhorias de performance. Tamb&amp;#233;m gostaria de fazer os testes com diferentes configura&amp;#231;&amp;#245;es de hardware.&lt;br /&gt;Entretanto estive com bastantes dificuldades em fazer os testes funcionarem. Eles apresentaram um comportamento an&amp;#244;malo (leia-se imprevis&amp;#237;vel) na m&amp;#225;quina em que iniciei os testes, e atribui o problema &amp;#224; arquitetura 64bits da nova m&amp;#225;quina. Mudando para um processador 32 bits n&amp;#227;o tenho problemas com a compila&amp;#231;&amp;#227;o, entretanto estou tendo problemas com os kernels, que falham em sua execu&amp;#231;ao. Acredito ser um pequeno problema com a mudan&amp;#231;a do compilador (1.0 -&amp;gt; 2.2), mas ainda n&amp;#227;o consegui identific&amp;#225;-lo.&lt;br /&gt;Estarei postando aqui em breve um relat&amp;#243;rio de meus testes.&lt;br /&gt;&lt;br /&gt;Fora isso continuo estudando OpenCl, o que &amp;#233; bastante parecido com Cuda, assim que vou 'com as duas ao mesmo tempo'.&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;28/08/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estive estudando uma maneira de gerenciar automaticamente a inclus&amp;#227;o da DLL (como citado no post anterior). Postei algumas perguntas no blog da MSDN e obtive algumas respostas interessantes, que devem ser testadas nos proximos dias.&lt;br /&gt;&lt;br /&gt;Estive tamb&amp;#233;m estudando nessas &amp;#250;ltimas semanas &lt;b&gt;OpenCl&lt;/b&gt;.&lt;br /&gt;OpenCl &amp;#233; uma linguagem inicialmente criada pela Apple - e que teve como colaboradores a Intel, a nVidia e a AMD - para escrever programas que executem em ambientes heterogeneos, compostos de GPUs e CPUs.&lt;br /&gt;A linguagem foi 'abra&amp;#231;ada' pelo Kronos Group, que disponibilizou recentemente a especifica&amp;#231;&amp;#227;o da vers&amp;#227;o 1.0.&lt;br /&gt;Atualmente existem apenas vers&amp;#245;es beta dos drivers (visto que o kronos group somente disponibiliza a especifica&amp;#231;&amp;#227;o, cabe &amp;#224;s fabricantes de hardware gr&amp;#225;fico implementarem essa especifica&amp;#231;&amp;#227;o e fornecerem um compilador e um driver/sdk.&lt;br /&gt;&lt;br /&gt;Eu estou aqui testando com o driver beta da nvidia (apenas para desenvolvedores registrados). A implementa&amp;#231;&amp;#227;o da nVidia nada mais &amp;#233; que um 'mapeamento' da arquitetura CUDA para o OpenCl (creio que isso seja pr&amp;#243;ximo ao que a AMD/ATI est&amp;#225; fazendo, mapeando n&amp;#227;o para o CUDA mas para o Stream).&lt;br /&gt;&lt;br /&gt;Em CUDA, as fun&amp;#231;&amp;#245;es que se utilizam do paralelismo da GPU s&amp;#227;o conhecidas como &lt;i&gt;kernels&lt;/i&gt;.&lt;br /&gt;Kernels s&amp;#227;o executados por Streaming Multiprocessors (SMs). Cada SM, por sua vez, &amp;#233; composto por 8 Scalar Processors (SPs), os quais podem, cada um, executar simultaneamente at&amp;#233; 4 threads. Assim temos que um Streaming Multiprocessor pode executar simultaneamente at&amp;#233; 32 threads, o que chamaremos de &lt;i&gt;warp&lt;/i&gt;.&lt;br /&gt;Sempre que invocamos um kernel, especificamos para ele quantos &lt;i&gt;thread&lt;/i&gt; &lt;i&gt;blocks&lt;/i&gt; e quantas &lt;i&gt;threads&lt;/i&gt; &lt;i&gt;per&lt;/i&gt; &lt;i&gt;block&lt;/i&gt; queremos que esse kernel utilize. Cada SM encarrega-se da execu&amp;#231;&amp;#227;o de 1 thread block.&lt;br /&gt;Teoricamente, assim, se tivermos menos que 32 threads em um thread block estaremos 'perdendo processamento', pois n&amp;#227;o teremos preenchido o warp do SM. Se tivermos mais que 32 threads per block, entretanto, nossa situa&amp;#231;&amp;#227;o depender&amp;#225; da quantidade de mem&amp;#243;ria e de registradores que estar&amp;#227;o sendo utilizados. Funciona da seguinte forma: a CPU utiliza cache para esconder a latencia de mem&amp;#243;ria, i.e. para n&amp;#227;o termos que esperar sempre que os dados cheguem, n&amp;#243;s armazenamos-nos em uma cache. Na GPU escondemos a lat&amp;#234;ncia da mem&amp;#243;ria com computa&amp;#231;&amp;#245;es. Temos que a troca de contexto entre threads &amp;#233; muito veloz, assim ao inv&amp;#233;s de armazenarmos a mem&amp;#243;ria em uma grande cache, simplesmente mandamos outra thread executar enquanto esperamos, contanto que haja registradores livres no banco de registradores do SM.&lt;br /&gt;&lt;br /&gt;Em OpenCl temos a no&amp;#231;&amp;#227;o de &lt;i&gt;work-item&lt;/i&gt;s, que s&amp;#227;o mapeados para CUDA Threads, temos a no&amp;#231;&amp;#227;o de &lt;i&gt;work-groups&lt;/i&gt;, que s&amp;#227;o mapeados para thread blocks e por fim temos um NDRange, que &amp;#233; mapeado para um grid de thread blocks.&lt;br /&gt;O mapeamento &amp;#233; feito compilando OpenCl para o mesmo &amp;quot;bytecode&amp;quot;: PTX.&lt;br /&gt;&lt;br /&gt;Em breve estarei postando aqui trechos iniciais de c&amp;#243;digo em OpenCl, e espero estar fazendo alguns benchmarks com CUDA/OpenCl/CPU.&lt;br /&gt;&lt;br /&gt;Para maiores informa&amp;#231;&amp;#245;es a respeito das duas linguagens:
&lt;ul&gt;&lt;li&gt;Cuda:
&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.nvidia.com/object/cuda_home.html#" class="externalLink"&gt;http://www.nvidia.com/object/cuda_home.html#&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/CUDA" class="externalLink"&gt;http://en.wikipedia.org/wiki/CUDA&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ddj.com/hpc-high-performance-computing/207200659" class="externalLink"&gt;http://www.ddj.com/hpc-high-performance-computing/207200659&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;OpenCl
&lt;ul&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/OpenCL" class="externalLink"&gt;http://en.wikipedia.org/wiki/OpenCL&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.khronos.org/opencl/" class="externalLink"&gt;http://www.khronos.org/opencl/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.nvidia.com/object/cuda_opencl.html" class="externalLink"&gt;http://www.nvidia.com/object/cuda_opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ati.amd.com/technology/streamcomputing/opencl.html" class="externalLink"&gt;http://ati.amd.com/technology/streamcomputing/opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.openclworld.com/" class="externalLink"&gt;http://www.openclworld.com/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/07/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;Nesta semana estive com alguns problemas relativos &amp;#224; compatibilidade do debugger quando o projeto &amp;#233; levado a outros computadores. Esses problemas se deveram n&amp;#227;o &amp;#224; falta de compatibilidade do programa, mas sim do Package. Corrigi o problema, mas pretendo investigar a sua causa.&lt;br /&gt;Estou agora precisando ter acesso ao executavel gerado ap&amp;#243;s a compila&amp;#231;&amp;#227;o, estive dando uma olhada nisso nesta semana, sem muito sucesso. Al&amp;#233;m disso, preciso encontrar uma forma de manter sempre a DLL modificada como a acessivel pelo programa, ou seja, preciso de alguma forma manter a dll nas pastas do Visual Studio, no local onde o Package &amp;#233; instalado, e fazer com que tudo isso se ajeite na hora da instala&amp;#231;&amp;#227;o do pacote.&lt;br /&gt;Al&amp;#233;m desses pequenos problemas, continuo trabalhando na parte gr&amp;#225;fica (infelizmente n&amp;#227;o sou muito proficiente na cria&amp;#231;&amp;#227;o de interfaces amig&amp;#225;veis e bonitas) para integr&amp;#225;-la bem ao ambiente do Visual Studio. Ainda estou pensando em uma boa forma de dispor os compontentes, e em como melhorar a usabilidade do debugger.&lt;br /&gt;Fora isso ele se encontra bem integrado. &amp;#201; preciso fazer alguns testes, nos quais me dedicarei na pr&amp;#243;xima semana.&lt;br /&gt;&lt;br /&gt;At&amp;#233; la,&lt;br /&gt;&lt;br /&gt;Leonardo&lt;br /&gt;
&lt;h2&gt;08/07/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;Estou fazendo atualmente alguns ajustes automatizar mais o debugger, utilizando para isso as interface IVsRunningDocTableEvents, que implementa alguns m&amp;#233;todos para obter as notifica&amp;#231;&amp;#245;es sobre modifica&amp;#231;&amp;#245;es na IDE.&lt;br /&gt;Para poder passar a receber os eventos da IDE (que ser&amp;#227;o tratados pelos handlers da interface, a saber:
&lt;ul&gt;&lt;li&gt;int IVsRunningDocTableEvents.OnAfterAttributeChange&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterDocumentWindowHide&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterFirstDocumentLock&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterSave&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnBeforeDocumentWindowShow&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnBeforeLastDocumentUnlock&lt;/li&gt;&lt;/ul&gt;
)&lt;br /&gt;&lt;br /&gt;Esses eventos s&amp;#227;o importantes para que possamos ser notificados de modifica&amp;#231;&amp;#245;es importantes, como por exemplo saber quais s&amp;#227;o os documentos que est&amp;#227;o abertos.&lt;br /&gt;&lt;br /&gt;Para poder receber os eventos, devemos nos inscrever da seguinte forma:&lt;br /&gt;Declaramos inicialmente um cookie:
&lt;ul&gt;&lt;li&gt;uint cookie;&lt;/li&gt;&lt;/ul&gt;
E logo ap&amp;#243;s devemos declarar uma interface IVsRunningDocumentTable, e solicitar que ela avise sobre os eventos
&lt;ul&gt;&lt;li&gt;IVsRunningDocumentTable rdt = &lt;/li&gt;&lt;/ul&gt;
                (IVsRunningDocumentTable)Package.GetGlobalService(typeof(SVsRunningDocumentTable));
&lt;ul&gt;&lt;li&gt;rdt.AdviseRunningDocTableEvents(this, out dwCookie);&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Em breve, novas novidades.&lt;br /&gt;At&amp;#233;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;11/06/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;infelizemente, ap&amp;#243;s algum tempo de estudo em cima do debugger de exemplo, feito por Jackson Davis, dispon&amp;#237;vel em &lt;a href="http://code.msdn.microsoft.com/debugenginesample" class="externalLink"&gt;http://code.msdn.microsoft.com/debugenginesample&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;, e ap&amp;#243;s uma troca de e-mails com o mesmo, constatei que o desenvolvimento de uma debug engine para o VS, ou seja, o objetivo inicial de integrar totalmente o debugger de GLSL com o debugger do Visual Studio &amp;#233; demasiado complexa, visto que h&amp;#225; um grande n&amp;#250;mero de interfaces a implementar e que aparentemente o debugger de GLSL n&amp;#227;o &amp;#233; compat&amp;#237;vel com o modelo de debug engine que o Visual Studio espera. Com certeza ha uma maneira de realizar essa integra&amp;#231;ao, fazendo as devidas modifica&amp;#231;&amp;#245;es no debugger e implementando as interfaces requeridas pelo VS, mas esse trabalho levar&amp;#225; muito tempo.&lt;br /&gt;Portanto, dadas as condi&amp;#231;&amp;#245;es, optamos por desenvolver o depurador de forma externa ao depurador do Visual Studio, como j&amp;#225; vinha sendo feito em paralelo. Existe uma quantidade consideravel de melhorias que se podem fazer e &amp;#233; esse o atual objetivo.&lt;br /&gt;Tendo em vista o atual foco do trabalho, em pouco tempo espero estar postando alguns print screens e releases do debugger 'integrado'.&lt;br /&gt;&lt;br /&gt;Obrigado,&lt;br /&gt;&lt;br /&gt;Leonardo&lt;br /&gt;
&lt;h2&gt;26/05/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estou utilizando os objetos DTE e DTE2 para alguns testes. Ainda tive alguns problemas ap&amp;#243;s o &amp;#250;ltimo post para conseguir o objeto, mas agora essa j&amp;#225; &amp;#233; uma quest&amp;#227;o do passado.&lt;br /&gt;Estive nessas semanas estudando os objetos DTE e DTE2 e tamb&amp;#233;m estudando um projeto de exemplo de um depurador C&lt;u&gt;&lt;/u&gt; integrado ao Visual Studio. Os resultados desse estudo ainda n&amp;#227;o s&amp;#227;o vis&amp;#237;veis no depurador GLSL.&lt;br /&gt;Quanto a altera&amp;#231;oes no depurador, coloquei uma lista com os shaders sendo editados no projeto, de forma que o usu&amp;#225;rio possa escolher mais facilmente qual o shader a ser escolhido. Vou seguir com algumas altera&amp;#231;&amp;#245;es visuais desse estilo para deixar o debugger mais amig&amp;#225;vel.&lt;br /&gt;&lt;br /&gt;At&amp;#233;&lt;br /&gt;
&lt;h2&gt;12/05/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;ontem descobri uma solu&amp;#231;&amp;#227;o interessante para um pequeno problema que me atormentou por bastante tempo e que pelo visto atormenta bastante gente ainda.&lt;br /&gt;Para solucionar uma s&amp;#233;rie de quest&amp;#245;es ao desenvolver VSPackages, podemos utilizar o &amp;quot;automation object&amp;quot; DTE, que representa o objeto de mais alta hierarquia no ambiente EnvDTE, que possui referencias a todos os elementos da automa&amp;#231;&amp;#227;o do n&amp;#250;cleo do VS. Para tanto declaramos uma interface DTE, pertencente ao namespace EnvDTE (&amp;#233; necess&amp;#225;rio adicionar uma Reference ao projeto: EnvDTE), e utilizamos o m&amp;#233;todo GetService para recuperar o objeto DTE (ele ser&amp;#225; referenciado pela interface DTE que declaramos).&lt;br /&gt;Pretendo colocar mais explica&amp;#231;&amp;#245;es sobre o objeto DTE nos proximos post, mas agora quero me concentrar na explica&amp;#231;&amp;#227;o e solu&amp;#231;&amp;#227;o do problema que me atormentou.&lt;br /&gt;Eis que o seguinte c&amp;#243;digo &amp;#233; o respons&amp;#225;vel por declarar e recuperar o objeto DTE:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; EnvDTE;

DTE dte;

&lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Initialize() {
&lt;span style="color:Green;"&gt;//Inicializa&amp;#231;&amp;#245;es&lt;/span&gt;

&lt;span style="color:Blue;"&gt;this&lt;/span&gt;.dte = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SDTE)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; DTE;
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Entretanto, ap&amp;#243;s a execu&amp;#231;&amp;#227;o do trecho, dte continuava sempre com valor null, o que acabava gerando exce&amp;#231;&amp;#245;es e obviamente n&amp;#227;o era o que deveria estar acontecendo.&lt;br /&gt;Buscando na internet, encontrei no VSX Team Blog (o blog do pessoal do VSX (Visual Studio Extensibility)) a solu&amp;#231;&amp;#227;o para meu problema.&lt;br /&gt;O fato &amp;#233; que caso o ambiente n&amp;#227;o esteja totalmente carregado (em &amp;quot;zombie state&amp;quot;), a solicita&amp;#231;&amp;#227;o da referencia do objeto DTE retorna null. Como eu queria que o package fosse carregado juntamente com o VS (no startup), a inicializa&amp;#231;&amp;#227;o do package ocorria antes de o ambiente estar totalmente carregado, e dte continha sempre o valor null.&lt;br /&gt;Assim, a solu&amp;#231;&amp;#227;o proposta pelo pessoal do blog &amp;#233; a seguinte: utilizar a interface IVsShellPropertyEvents, implementando o handler OnShellPropertyChange, o qual faz o tracking do estado da IDE. A propriedade que diz se o VS est&amp;#225; zombie &amp;#233; a VSPROPID_Zombie.&lt;br /&gt;Segue abaixo a implementa&amp;#231;&amp;#227;o do blog do pessoal do VSX:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
      DTE dte;
      &lt;span style="color:Blue;"&gt;uint&lt;/span&gt; cookie;
      &lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Initialize()
      {
           &lt;span style="color:Blue;"&gt;base&lt;/span&gt;.Initialize();
           IVsShell shellService = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsShell)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; IVsShell;
           &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (shellService != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
                ErrorHandler.ThrowOnFailure(shellService.AdviseShellPropertyChanges(&lt;span style="color:Blue;"&gt;this&lt;/span&gt;,&lt;span style="color:Blue;"&gt;out&lt;/span&gt; cookie));
           ...
        }

        &lt;span style="color:Blue;"&gt;#region&lt;/span&gt; IVsShellPropertyEvents Members

        &lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;int&lt;/span&gt; OnShellPropertyChange(&lt;span style="color:Blue;"&gt;int&lt;/span&gt; propid, &lt;span style="color:Blue;"&gt;object&lt;/span&gt; &lt;span style="color:Blue;"&gt;var&lt;/span&gt;)
        {
            &lt;span style="color:Green;"&gt;// when zombie state changes to false, finish package initialization&lt;/span&gt;
            &lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((&lt;span style="color:Blue;"&gt;int&lt;/span&gt;)__VSSPROPID.VSSPROPID_Zombie == propid)
            {
                &lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((&lt;span style="color:Blue;"&gt;bool&lt;/span&gt;)&lt;span style="color:Blue;"&gt;var&lt;/span&gt; == &lt;span style="color:Blue;"&gt;false&lt;/span&gt;)
                {
                    &lt;span style="color:Green;"&gt;// zombie state dependent code&lt;/span&gt;
                    &lt;span style="color:Blue;"&gt;this&lt;/span&gt;.dte = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SDTE)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; DTE;
                    &lt;span style="color:Green;"&gt;// eventlistener no longer needed&lt;/span&gt;
                    IVsShell shellService = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsShell)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; IVsShell;
                    &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (shellService != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
                        ErrorHandler.ThrowOnFailure(shellService.UnadviseShellPropertyChanges(&lt;span style="color:Blue;"&gt;this&lt;/span&gt;.cookie));
                    &lt;span style="color:Blue;"&gt;this&lt;/span&gt;.cookie = 0;
                }
            }

            &lt;span style="color:Blue;"&gt;return&lt;/span&gt; VSConstants.S_OK;

        }

        &lt;span style="color:Blue;"&gt;#endregion&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Esse artigo pode ser encontrado em &lt;a href="http://blogs.msdn.com/vsxteam/archive/2008/06/09/dr-ex-why-does-getservice-typeof-envdte-dte-return-null.aspx" class="externalLink"&gt;http://blogs.msdn.com/vsxteam/archive/2008/06/09/dr-ex-why-does-getservice-typeof-envdte-dte-return-null.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Nos proximos posts estarei descrevendo mais a fundo a parte t&amp;#233;cnica do VS que estudei at&amp;#233; agora, e introduzirei alguns dos problemas futuros que pretendo estar resolvendo.&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;06/05/09&lt;/h2&gt;Ol&amp;#225;,&lt;br /&gt;nestas ultimas semanas estive um pouco sobrecarregado, e n&amp;#227;o tive muito tempo para escrever no blog. A primeira etapa da depura&amp;#231;&amp;#227;o j&amp;#225; esta concluida, entretanto restam alguns bugs relativos ao depurador que devem ser resolvidos antes de ser lan&amp;#231;ado um release do plug-in.&lt;br /&gt;Venho trabalhando na parte mais profunda da integra&amp;#231;&amp;#227;o.&lt;br /&gt;Al&amp;#233;m da mera quest&amp;#227;o de mapear as funcionalidades do depurador para a IDE (que n&amp;#227;o &amp;#233; trivial), restam alguns problemas que surgem do fato de que algumas features existentes no VS n&amp;#227;o se encontram atualmente no depurador (como por exemplo a utiliza&amp;#231;&amp;#227;o de breakpoints). Essas funcionalidades dever&amp;#227;o ser implementadas em breve.&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/04/09&lt;/h2&gt;Oi,&lt;br /&gt;nesta semana finalizei uma primeira integra&amp;#231;&amp;#227;o. Neste primeiro est&amp;#225;gio temos, como j&amp;#225; foi dito, o depurador da B&amp;#225;rbara executando sobre o Visual Studio.&lt;br /&gt;H&amp;#225; ainda uma s&amp;#233;rie de melhorias que devem ser feitas sobre esta integra&amp;#231;&amp;#227;o:
&lt;ul&gt;&lt;li&gt;Melhorias na estrutura&amp;#231;&amp;#227;o e organiza&amp;#231;&amp;#227;o do c&amp;#243;digo;&lt;/li&gt;
&lt;li&gt;Remo&amp;#231;&amp;#227;o de alguns bugs;&lt;/li&gt;
&lt;li&gt;Melhor organiza&amp;#231;&amp;#227;o visual;&lt;/li&gt;&lt;/ul&gt;
At&amp;#233; o fim desta semana planejo ter uma vers&amp;#227;o utilizavel do depurador, melhor organizada visualmente, com algumas funcionalidades a mais (no que toca &amp;#224; integra&amp;#231;&amp;#227;o, por exemplo que o depurador saiba qual o shader que deve ser depurado automaticamente, assim como o programa opengl.&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;20/04/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estou tendo alguns problemas na integra&amp;#231;&amp;#227;o, que derivam diretamente de d&amp;#250;vidas com rela&amp;#231;&amp;#227;o ao depurador desenvolvido pela Barbara.&lt;br /&gt;A id&amp;#233;ia desta primeira integra&amp;#231;&amp;#227;o &amp;#233; bastante simples, uma simples adi&amp;#231;&amp;#227;o do depurador da barbara sobre o VS. A id&amp;#233;ia &amp;#233; que ap&amp;#243;s essa etapa seja construido incrementalmente o depurador integrado. Nesse ponto temos algumas dificuldades, como por exemplo que o depurador n&amp;#227;o suporta a coloca&amp;#231;&amp;#227;o de breakpoints, mas executa sempre passo a passo, de forma que n&amp;#227;o se pode definir de forma mais flexivel o fluxo do programa.&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;10/04/09&lt;/h2&gt;Ol&amp;#225;,&lt;br /&gt;nesta semana estive trabalhando na efetiva integra&amp;#231;&amp;#227;o do Depurador GLSL para o VS2008. A id&amp;#233;ia inicial inserir apenas o depurador de forma externa ao depurador do Visual Studio, o que &amp;#233; uma tarefa mais simples e deve ser terminada at&amp;#233; o final da semana. Nos proximos posts estarei publicando screenshots e maiores explica&amp;#231;&amp;#245;es sobre essa integra&amp;#231;&amp;#227;o. Esse trabalho tem a vantagem de que o depurador estar&amp;#225; rapidamente pronto para ser utilizado, entretanto ele n&amp;#227;o estara integrado com o depurador do Visual Studio. Para acess&amp;#225;-lo haver&amp;#227;o menus e janelas exclusivas que se encarregar&amp;#227;o de realizar todo o processo.&lt;br /&gt;Ap&amp;#243;s terminar essa primeira etapa de integra&amp;#231;&amp;#227;o, pretendo construir uma Debug Engine que se comunique com a SDM e torne o processo de depura&amp;#231;&amp;#227;o transparente ao usu&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;01/04/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;nas semanas anteriores eu estive estudando o desenvolvimento de VSPackages gen&amp;#233;ricos, como uma forma de me familiarizar com eles. Nesta semana, e nas que vir&amp;#227;o, me voltei efetivamente para o VSDebugger e como extend&amp;#234;-lo.&lt;br /&gt;&lt;br /&gt;Basicamente o debugger do visual studio &amp;#233; composto de tr&amp;#234;s partes:
&lt;ul&gt;&lt;li&gt;Interface com o usu&amp;#225;rio (UI), que permite, por exemplo, que sejam colocados breakpoints, que o codigo seja executado instru&amp;#231;&amp;#227;o a instru&amp;#231;&amp;#227;o, etc.&lt;/li&gt;
&lt;li&gt;SDM (Session Debug Manager), que &amp;#233; basicamente quem gerencia as Debug Engines. Pode ser visto como um multiplexador de Debug Engines, al&amp;#233;m de fazer a comunica&amp;#231;&amp;#227;o com a UI. A SDM &amp;#233; implementada pelo VS e n&amp;#227;o ser&amp;#225; alterada.&lt;/li&gt;
&lt;li&gt;Debug Engine (DE), que &amp;#233; o elemento que efetivamente faz a depura&amp;#231;&amp;#227;o do programa, e se comunica com a SDM. &amp;#201; aqui que ser&amp;#225; introduzido o depurador de GLSL.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Assim, teremos que construir uma DE que incorpore o depurador desenvolvido pela B&amp;#225;rbara. Para construir uma DE, s&amp;#227;o necess&amp;#225;rios alguns passos:
&lt;ul&gt;&lt;li&gt;Primeiro devemos registrar nossa DE no Visual Studio, permitindo que ele a reconhe&amp;#231;a e utilize;&lt;/li&gt;
&lt;li&gt;Nossa DE deve, quando solicitado pela SDM, &amp;quot;conectar-se&amp;quot; ao programa a ser depurado. Isso ocorre quando o usu&amp;#225;rio escolhe depurar o programa. Ocorre ent&amp;#227;o uma troca de mensagens entre a SDM e as DEs;&lt;/li&gt;
&lt;li&gt;Agora que nossa DE est&amp;#225; &amp;quot;conectada&amp;quot; ao programa efetivamente podemos nos concentrar em depurar o programa. Esta etapa consiste em:
&lt;ul&gt;&lt;li&gt;Controlar o fluxo de execu&amp;#231;&amp;#227;o, respeitando breakpoints e execu&amp;#231;&amp;#227;o step-by-step;&lt;/li&gt;
&lt;li&gt;Comunicar-se com a SDM, fazendo com que tanto o VS quanto o usu&amp;#225;rio tenham um feedback da depura&amp;#231;&amp;#227;o;&lt;/li&gt;
&lt;li&gt;Al&amp;#233;m disso temos que permitir:
&lt;ul&gt;&lt;li&gt;A cria&amp;#231;&amp;#227;o/dele&amp;#231;&amp;#227;o de breakpoints;&lt;/li&gt;
&lt;li&gt;A inser&amp;#231;&amp;#227;o de watches;&lt;/li&gt;
&lt;li&gt;A visualiza&amp;#231;&amp;#227;o da pilha de chamadas;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;A seguir devemos nos desconectar do programa e solicitar &amp;#224; SDM para que o mesmo seja terminado;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Neste momento estou estudando um pouco mais o trabalho da B&amp;#225;rbara. Minhas d&amp;#250;vidas se concentram em como exatamente integrar todo o sistema de debugging do Visual Studio ao depurador que j&amp;#225; foi desenvolvido. Nos pr&amp;#243;ximos posts procurarei explicar um pouco melhor o funcionamento do mecanismo de depura&amp;#231;&amp;#227;o do VS, al&amp;#233;m de tentar aproximar um pouco mais os dois debuggers.&lt;br /&gt;&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;25/03/09 - Hello World&lt;/h2&gt;Nesta semana continuei a estudar o desenvolvimento de um Package para o VS2008. O estudo foi dirigido basicamente aos procedimentos de cria&amp;#231;&amp;#227;o e ao funcionamento dos recursos gerados pelo wizard.&lt;br /&gt;&lt;br /&gt;Para iniciar o desenvolvimento de um VSPackage, ap&amp;#243;s baixar o SDK do Visual Studio, &amp;#233; utilizar o wizard de cria&amp;#231;&amp;#227;o de package, que se encarrega de gerar o c&amp;#243;digo base, deixando para n&amp;#243;s apenas o desenvolvimento do Package.&lt;br /&gt;Assim, ap&amp;#243;s definir o nome de nosso Package, somos perguntados a respeito de algumas coisas sobre o ele: a linguagem em que o desenvolveremos, se queremos uma Tool Window, um Menu Tool, etc.&lt;br /&gt;Para construir o Hello World utilizei C# e criei tanto uma Tool Window quanto um Menu Tool.&lt;br /&gt;Os resultados foram os seguintes:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Window&lt;/b&gt; &lt;b&gt;Tool:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63149" alt="windowTool.bmp" title="windowTool.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63150" alt="windowTool2.bmp" title="windowTool2.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo Fonte&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; okButton_Click(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, System.EventArgs e)
        {
            MessageBox.Show(&lt;span style="color:#A31515;"&gt;&amp;quot;Seu nome &amp;#233; &amp;quot;&lt;/span&gt; + nameBox.Text.ToString(), &lt;span style="color:#A31515;"&gt;&amp;quot;Seu nome&amp;quot;&lt;/span&gt;, MessageBoxButtons.OK);
        }

        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; limparButton_Click(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, System.EventArgs e)
        {
            nameBox.Text = &lt;span style="color:#A31515;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;;
        }

&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Command Tool:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63151" alt="cmdTool.bmp" title="cmdTool.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo fonte do command:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; MenuItemCallback(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, EventArgs e)
        {
            &lt;span style="color:Green;"&gt;// Show a Message Box to prove we were here&lt;/span&gt;
            IVsUIShell uiShell = (IVsUIShell)GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsUIShell));
            Guid clsid = Guid.Empty;
            &lt;span style="color:Blue;"&gt;int&lt;/span&gt; result;
            Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(uiShell.ShowMessageBox(
                       0,
                       &lt;span style="color:Blue;"&gt;ref&lt;/span&gt; clsid,
                       &lt;span style="color:#A31515;"&gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;,
                       &lt;span style="color:Blue;"&gt;string&lt;/span&gt;.Format(CultureInfo.CurrentCulture, &lt;span style="color:#A31515;"&gt;&amp;quot;Hello World - Este &amp;#233; um menuTool&amp;quot;&lt;/span&gt;),
                       &lt;span style="color:Blue;"&gt;string&lt;/span&gt;.Empty,
                       0,
                       OLEMSGBUTTON.OLEMSGBUTTON_OK,
                       OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST,
                       OLEMSGICON.OLEMSGICON_INFO,
                       0,        &lt;span style="color:Green;"&gt;// false&lt;/span&gt;
                       &lt;span style="color:Blue;"&gt;out&lt;/span&gt; result));
        }
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Nos proximos posts estarei explicando com mais detalhes o funcionamento desses elementos. Atualmente estou buscando algo mais proximo do debugger, assim que possivelmente nos proximos posts n&amp;#227;o estarei mais lidando com exemplos gen&amp;#233;ricos, mas com algo mais focado no debugger em si.&lt;br /&gt;Uma &amp;#243;tima refer&amp;#234;ncia (em ingles) &amp;#233; &lt;a href="http://learnvsxnow.codeplex.com/" class="externalLink"&gt;http://learnvsxnow.codeplex.com/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;17/03/09&lt;/h2&gt;Oi pessoal,&lt;br /&gt;sou o Leonardo e este &amp;#233; meu primeiro post aqui.&lt;br /&gt;Atualmente, como a Barbara comentou, estou estudando o desenvolvimento de um &amp;quot;plug-in&amp;quot; para o Visual Studio, que permita a integra&amp;#231;&amp;#227;o do trabalho dela com o ambiente de desenvolvimento, facilitando assim o trabalho de depura&amp;#231;&amp;#227;o.&lt;br /&gt;A id&amp;#233;ia &amp;#233; tornar o depurador natural ao usu&amp;#225;rio do VS.&lt;br /&gt;&lt;br /&gt;O desenvolvimento se far&amp;#225; a partir de VSPackages, que s&amp;#227;o a ferramenta de extensibilidade mas completa que a Microsoft prov&amp;#234; para o Visual Studio.&lt;br /&gt;&lt;br /&gt;Mais informa&amp;#231;&amp;#245;es sobre Visual Studio Extensibility, al&amp;#233;m do download dos SDKs do VS2005 e VS208, podem ser encontradas aqui: &lt;a href="http://msdn.microsoft.com/en-us/vsx/default.aspx" class="externalLink"&gt;http://msdn.microsoft.com/en-us/vsx/default.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; (Visual Studio Extensibility Developer Center).&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;08/03/2009&lt;/h2&gt;Nesta semana trabalhei corrigindo problemas na interface e procurei deixar o c&amp;#243;digo do depurador menos &amp;quot;duro&amp;quot;. Como por exemplo, poder abrir os arquivos em qualquer ordem e n&amp;#227;o primeiro um tipo de shader e depois o outro.&lt;br /&gt;
&lt;h2&gt;24/02/2009&lt;/h2&gt;Em virtude da troca de bolsistas, optamos por focar no desenvolvimento do plugin para o Visual Studio. Desta forma, o Leonardo est&amp;#225; estudando o desenvolvimento de plugins, enquanto eu estou arrumando o c&amp;#243;digo para que esta integra&amp;#231;&amp;#227;o possa ser feita.&lt;br /&gt;
&lt;h2&gt;18/02/2009&lt;/h2&gt;Fui aprovada para o Mestrado em Ci&amp;#234;ncia da Computa&amp;#231;&amp;#227;o - UFRGS, desta forma, a partir de mar&amp;#231;o estarei afastada do projeto. Quem ir&amp;#225; dar continuidade ao projeto &amp;#233; o aluno no quinto semestre de gradua&amp;#231;&amp;#227;o do curso de &lt;br /&gt;Ci&amp;#234;ncia da Computa&amp;#231;&amp;#227;o - UFRGS, Leonardo Chatain. Seja bem vindo, Leonardo!&lt;br /&gt;
&lt;h2&gt;18/01/2009&lt;/h2&gt;Como disse no &amp;#250;ltimo post, comecei a trabalhar na integra&amp;#231;&amp;#227;o da ferramenta com outras. &lt;br /&gt;A ferramenta com a qual estou fazendo integra&amp;#231;&amp;#227;o &amp;#233; a Shader Designer. A principal dificuldade encontrada at&amp;#233; o momento est&amp;#225; sendo portar o projeto da Shader Designer do Microsoft Visual Studio 2003 para o 2008 (ambiente em que foi desenvolvido o depurador). Estou tendo que re-escrever praticamente todo o c&amp;#243;digo. Al&amp;#233;m de que, o Shader Designer utiliza uma s&amp;#233;rie de c&amp;#243;digos fontes e de bibliotecas de terceiros (vide abaixo) que tamb&amp;#233;m est&amp;#227;o sendo portados. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digos Fontes de terceiros&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;a) 3DLabs GLSL Open Source Compiler &lt;br /&gt;&lt;br /&gt;b) Algumas fun&amp;#231;&amp;#245;es da &amp;quot;Matrix and Quaternion fAQ&amp;quot; &lt;br /&gt;&lt;br /&gt;c) AVI exporter &lt;br /&gt;&lt;br /&gt;d) GLEW Extensions manager.&lt;br /&gt;&lt;br /&gt;e) MeshMender da Nvidia&lt;br /&gt;&lt;br /&gt;f) DEV-IL&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Bibliotecas de terceiros&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;a) Compona's SyntaxBox. &lt;br /&gt;&lt;br /&gt;b) Flexporter&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;15/12/2008&lt;/h2&gt;Nestas &amp;#250;ltimas semanas escrevi e apresentei um trabalho acad&amp;#234;mico sobre o assunto. A apresenta&amp;#231;&amp;#227;o pode ser obtida &lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=51900';"&gt;aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Tamb&amp;#233;m foram acrescentadas novas funcionalidades:
&lt;ul&gt;&lt;li&gt;Permite ao usu&amp;#225;rio optar por depurar:
&lt;ul&gt;&lt;li&gt;Apenas o shader;&lt;/li&gt;
&lt;li&gt;Apenas o programa OpenGL hospedeiro;&lt;/li&gt;
&lt;li&gt;Ambos.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;ul&gt;&lt;li&gt;Permite visualizar o valor atualizado das vari&amp;#225;veis que j&amp;#225; foram depuradas&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Nas pr&amp;#243;ximas semanas, vou iniciar o estudo sobre desenvolvimento de plugins e come&amp;#231;ar a integra&amp;#231;&amp;#227;o da ferramenta.&lt;br /&gt;
&lt;h2&gt;30/11/2008&lt;/h2&gt;Como dito no post anterior, foram muitas as dificuldades encontradas na utiliza&amp;#231;&amp;#227;o de extens&amp;#245;es para captura de dados da placa gr&amp;#225;fica.&lt;br /&gt;Para que outras pessoas que necessitem utilizar estas extens&amp;#245;es n&amp;#227;o enfrentem o mesmo problema (principalmente pela falta de documenta&amp;#231;&amp;#227;o e de exemplos de uso), coloquei na p&amp;#225;gina &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Capturing%20Data%20From%20Graphics%20Hardware&amp;referringTitle=Blog"&gt;Capturing Data From Graphics Hardware&lt;/a&gt;, uma explica&amp;#231;&amp;#227;o das extens&amp;#245;es utilizadas com exemplos. &lt;br /&gt;&lt;br /&gt;O depurador foi aprimorado. Agora &amp;#233; poss&amp;#237;vel n&amp;#227;o apenas ver o resultado da vari&amp;#225;vel que est&amp;#225; sendo depurada, mas tamb&amp;#233;m das fun&amp;#231;&amp;#245;es pr&amp;#233;-definidas da OpenGL Al&amp;#233;m disto, foi escrito um trabalho acad&amp;#234;mico sobre o assunto, que ap&amp;#243;s sua apresenta&amp;#231;&amp;#227;o, tamb&amp;#233;m estar&amp;#225; dispon&amp;#237;vel aqui no CodePlex.&lt;br /&gt;&lt;br /&gt;Em breve tamb&amp;#233;m estarei disponibilizando um realease do depurador.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;30/10/2008 - Finishing the Debugger&lt;/h2&gt;Durante este m&amp;#234;s me foquei em terminar o depurador GLSL.&lt;br /&gt;Foram muitas as dificuldades encontradas, principalmente na utiliza&amp;#231;&amp;#227;o de extens&amp;#245;es para capturar a sa&amp;#237;da dos processadores de v&amp;#233;rtices e de fragmentos.&lt;br /&gt;Foram implementados 3 m&amp;#243;dulos:
&lt;ul&gt;&lt;li&gt;Wrapper OpenGL -&amp;gt; respons&amp;#225;vel por capturar as opera&amp;#231;&amp;#245;es OpenGL realizadas pelo programa OpenGL hospedeiro e inserir os c&amp;#243;digos necess&amp;#225;rios para depura&amp;#231;&amp;#227;o;&lt;/li&gt;
&lt;li&gt;Parser GLSL -&amp;gt; respons&amp;#225;vel por re-escrever o c&amp;#243;digo do shader GLSL de modo a inserir as vari&amp;#225;veis de depura&amp;#231;&amp;#227;o necess&amp;#225;rias&lt;/li&gt;
&lt;li&gt;Interfce Gr&amp;#225;fica -&amp;gt; respons&amp;#225;vel por interligar e utilizar os resultados obtidos nos demais m&amp;#243;dulos, al&amp;#233;m de, &amp;#233; claro, ser a interface com o usu&amp;#225;rio.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Este trabalho foi apresentado no &lt;a href="http://www.propesq.ufrgs.br/sic2008/index.htm" class="externalLink"&gt;XX Sal&amp;#227;o de IC - UFRGS&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. A apresenta&amp;#231;&amp;#227;o pode ser baixada &lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=47908';"&gt;aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Para as pr&amp;#243;ximas semanas pretendo continuar trabalhando no aprimoramento da ferramenta e escrever um documento mais detalhado sobre seu desenvolvimento.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;30/09/2008 - GLSL Debugger&lt;/h2&gt;
Passei algum tempo sem postar no blog. Durante este tempo estava trabalhando em uma nova etapa do projeto, o desenvolvimento de um plugin de depura&amp;#231;&amp;#227;o de GLSL para o Visual Studio. Maiores detalhes do andamento e da descri&amp;#231;&amp;#227;o desta etapa podem ser encontrados em &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=GLSL%20Debugger&amp;referringTitle=Blog"&gt;GLSL Debugger&lt;/a&gt;.&lt;br /&gt;
&lt;h2&gt;18/08/2008&lt;/h2&gt;GLSL n&amp;#227;o possui suporte &amp;#224; cast impl&amp;#237;cito (ex: vec4 color = 0.5;) assim, acrescentei o cast explicito (ex: vec4 color = vec4(0.5); )&lt;br /&gt;&lt;br /&gt;Continuei com os testes do programa. A principal dificuldade encontrada nos testes &amp;#233; a valida&amp;#231;&amp;#227;o. Por enquanto, o m&amp;#233;todo utilizado para os testes consiste em pegar um c&amp;#243;digo HLSL v&amp;#225;lido, converter e testar em um compilador GLSL se o c&amp;#243;digo gerado &amp;#233; v&amp;#225;lido ou n&amp;#227;o. Se n&amp;#227;o for, o programa &amp;#233; corrigido. Ou seja, por falta de uma BNF oficial da HLSL, nossos testes s&amp;#227;o baseados em exemplos. O que n&amp;#227;o &amp;#233; o ideal. A id&amp;#233;ia &amp;#233; que a pr&amp;#243;xima etapa de testes seja realizada comparando as imagens geradas. Ou seja, ser&amp;#227;o obtidas imagens executando o shader HLSL e estas ser&amp;#227;o comparadas com as imagens obtidas atrav&amp;#233;s da execu&amp;#231;&amp;#227;o do shader GLSL. A diferen&amp;#231;a entre estas imagens nos dir&amp;#225; o percentual de erro obtido na convers&amp;#227;o. &amp;#201; mais uma forma de validar o programa, por&amp;#233;m, o fato dos testes serem baseados em exemplos persiste. Para que este fator n&amp;#227;o seja t&amp;#227;o relevante, estamos utilizando uma gama variada de exemplos.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;04/08/2008&lt;/h2&gt;Como o programa estava dispon&amp;#237;vel apenas em vers&amp;#245;es de linha de comando, desenvolvi uma vers&amp;#227;o que apresenta uma interface gr&amp;#225;fica simplificada. Com esta interface, basta o usu&amp;#225;rio carregar o c&amp;#243;digo HLSL e clicar em converter. Os c&amp;#243;digos s&amp;#227;o exibidos lado &amp;#224; lado, facilitando a visualiza&amp;#231;&amp;#227;o pelo usu&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;Esta interface apresenta um limitante, que &amp;#233; o fato de ser compat&amp;#237;vel apenas com sistemas Windows. Por&amp;#233;m, em breve, pretendo desenvolver uma vers&amp;#227;o compat&amp;#237;vel com outros sistemas.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;24/07/2008&lt;/h2&gt;GLSL n&amp;#227;o apresenta suporte ao comando &amp;quot;Switch&amp;quot;. Desta forma, fiz uma fun&amp;#231;&amp;#227;o que substitui este comando por &amp;quot;If..else&amp;quot;.&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;        switch ( teste ) {
    			case 0: k++; return teste; 
    			case 1: return teste; 
    			case 2: t++; return teste; 
    			default: { 
    				teste++;
       			} 
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;      if (teste == 0) { k++; return teste; }
      else if (teste == 1) { return teste;}
      else if (teste == 2) { t++; return teste; }
      else { teste++;  }
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;GLSL n&amp;#227;o permite atribui&amp;#231;&amp;#245;es para elementos dos vetores, se estes vetores forem vari&amp;#225;veis to tipo &amp;quot;varying&amp;quot;. Ent&amp;#227;o, fiz uma fun&amp;#231;&amp;#227;o que cria uma vari&amp;#225;vel tempor&amp;#225;ria, efetua a atribui&amp;#231;&amp;#227;o e ent&amp;#227;o atribui o valor &amp;#224; vari&amp;#225;vel original.&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;  float4 MyShader( float2 Tex : TEXCOORD0 ) : COLOR0
{
    float4 Color;
    
    Color = float4(1.0,1.0,1.0,1.0);
    Color.a;
    Color.a = 0.1;
    Color.rgb = float3(0.5f);

    Tex.y = Tex.y + (sin(timeraslow)*0.01);
    Tex.x = Tex.x + (cos(timeraslow)*0.01);
    Color = tex2D( g_samSrcColor, Tex.xy);

    Color -= tex2D( g_samSrcColor, Tex.xy-0.001)*2.0f;
    Color += tex2D( g_samSrcColor, Tex.xy+0.001)*2.0f;
    Color.rgb = float3((Color.r+Color.g+Color.b)/3.0f);   	
   	
    return Color;
}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt; varying vec2 Tex;

void main( )
{
    vec4 Color;
    
    Color = vec4(1.0,1.0,1.0,1.0);
    Color.a;
    Color.a = 0.1;
    Color.rgb = vec3(0.5); //n&amp;#227;o necessita de vari&amp;#225;vel tempor&amp;#225;ria pois n&amp;#227;o &amp;#233; varying

    vec2 tempTex = Tex; //como Tex era varying foi criada uma vari&amp;#225;vel tempor&amp;#225;ria 

    tempTex.y = Tex.y + (sin(timeraslow)*0.01);
    Tex=tempTex;
    tempTex.x = Tex.x + (cos(timeraslow)*0.01);
    Tex=tempTex;
    Color = tex2D( g_samSrcColor, Tex.xy);

    Color -= tex2D( g_samSrcColor, Tex.xy-0.001)*2.0;
    Color += tex2D( g_samSrcColor, Tex.xy+0.001)*2.0;
    Color.rgb = vec3((Color.r+Color.g+Color.b)/3.0));   	
   	
    gl_FragColor = Color;
}
&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;09/07/2008&lt;/h2&gt;Acrescentei a convers&amp;#227;o das fun&amp;#231;&amp;#245;es intr&amp;#237;nsicas. Para as fun&amp;#231;&amp;#245;es intr&amp;#237;nsicas de HLSL que n&amp;#227;o s&amp;#227;o suportadas pela GLSL (vide &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Differences%20Between%20HLSL%20and%20GLSL&amp;referringTitle=Blog"&gt;Differences Between HLSL and GLSL&lt;/a&gt;), &amp;#233; emitida uma mensagem de aviso ao usu&amp;#225;rio.  GLSL tamb&amp;#233;m n&amp;#227;o suporta a letra 'f' ap&amp;#243;s um n&amp;#250;mero do tipo float (ex: 1.0f), ent&amp;#227;o, inseri uma fun&amp;#231;&amp;#227;o que remove este 'f' do n&amp;#250;mero. &lt;br /&gt;&lt;br /&gt;Iniciei tamb&amp;#233;m a fase de testes do programa. Para isto estou utilizando os shaders  &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Parsing%20Shaders&amp;referringTitle=Blog"&gt;Parsing Shaders&lt;/a&gt;. Ap&amp;#243;s converter, executo o arquivo gerado no software &lt;a href="http://www.opengl.org/sdk/tools/ShaderDesigner" class="externalLink"&gt;Shader Designer&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. Este software &amp;#233; um editor/compilador de GLSL. Assim, atrav&amp;#233;s de sua sa&amp;#237;da, posso verificar se o c&amp;#243;digo GLSL gerado &amp;#233; v&amp;#225;lido ou n&amp;#227;o e corrigir os problemas encontrados.&lt;br /&gt;&lt;br /&gt;A vers&amp;#227;o mais atual dos fontes do projeto encontra-se &lt;a href="http://www.codeplex.com/hl2glsl/SourceControl/ListDownloadableCommits.aspx" class="externalLink"&gt;dispon&amp;#237;vel&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;04/07/2008&lt;/h2&gt;Fiz algumas altera&amp;#231;&amp;#245;es na gram&amp;#225;tica e acrescentei novas fun&amp;#231;&amp;#245;es para tratar estas altera&amp;#231;&amp;#245;es.&lt;br /&gt;&lt;br /&gt;Altera&amp;#231;&amp;#245;es na gram&amp;#225;tica:&lt;br /&gt;*Reconhecimento do par&amp;#226;metro &amp;quot;: Register&amp;quot;;&lt;br /&gt;*Reconhecimento do par&amp;#226;metro &amp;quot;: Packoffset&amp;quot;;&lt;br /&gt;*Reconhecimento do operador un&amp;#225;rio &amp;quot;!&amp;quot;;&lt;br /&gt;*Reconhecimento do tipo &amp;quot;uint&amp;quot;.&lt;br /&gt;&lt;br /&gt;GLSL n&amp;#227;o apresenta suporte para acesso &amp;#224; registradores. Assim, os par&amp;#226;metros &amp;quot;register&amp;quot; e &amp;quot;packoffset&amp;quot; n&amp;#227;o podem ser utilizados. A medida adotada para solucionar este problema &amp;#233; avisar ao usu&amp;#225;rio deste fato e perguntar se ele deseja remover estes par&amp;#226;metros. Caso ele opte por n&amp;#227;o remover, um aviso de que o c&amp;#243;digo gerado ser&amp;#225; inconsistente &amp;#233; emitido.&lt;br /&gt;&lt;br /&gt;O caso do tipo &amp;quot;uint&amp;quot; &amp;#233; similar, pois tamb&amp;#233;m n&amp;#227;o &amp;#233; suportado pela GLSL. S&amp;#243; que ao inv&amp;#233;s de remover a vari&amp;#225;vel, a op&amp;#231;&amp;#227;o dada ao usu&amp;#225;rio &amp;#233; a de troc&amp;#225;-lo pelo tipo int. &lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;18/06/2008&lt;/h2&gt;Passei a utilizar o Source Code Client do CodePlex para disponibilizar o c&amp;#243;digo fonte.&lt;br /&gt;&lt;br /&gt;Acrescentei as fun&amp;#231;&amp;#245;es para tratar &amp;quot;return&amp;quot; e o tipo da fun&amp;#231;&amp;#227;o &amp;quot;main&amp;quot;.&lt;br /&gt;&lt;br /&gt;Em GLSL &amp;#233; necess&amp;#225;rio uma fun&amp;#231;&amp;#227;o void main() que &amp;#233; de onde iniciar&amp;#225; a execu&amp;#231;&amp;#227;o.  Em HLSL, isto n&amp;#227;o &amp;#233; necess&amp;#225;rio.&lt;br /&gt;Assim, &amp;#233; preciso substituir o nome da fun&amp;#231;&amp;#227;o em HLSL por &amp;quot;main&amp;quot; e o tipo da fun&amp;#231;&amp;#227;o por void. O tipo da fun&amp;#231;&amp;#227;o deve ser salvo pois ele ser&amp;#225; utilizado na sa&amp;#237;da da fun&amp;#231;&amp;#227;o.  &lt;br /&gt;&lt;br /&gt;Como a fun&amp;#231;&amp;#227;o em GLSL &amp;#233; do tipo void, ela n&amp;#227;o tem mais o &amp;quot;return&amp;quot;.  Sua sa&amp;#237;da vai ser determinada de acordo com o tipo e os par&amp;#226;metros sem&amp;#226;nticos da fun&amp;#231;&amp;#227;o original, &lt;br /&gt;&lt;br /&gt;Ex: &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;float4 pixelShader( float4 color):COLOR
{
          float4 teste =float4(0,1,0,0);
          float4 tes   = color + teste;

          return tes;
} &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;varying vec4 color;

void main() { 

	vec4 teste = vec4(0,1,0,0);
	vec4 tes   = color + teste;
	
	gl_FragColor = vec4(tes) ;  
} &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;02/06/2008&lt;/h2&gt;
Disponibilizei os fontes em desenvolvimento do projeto na sess&amp;#227;o Releases nas vers&amp;#245;es de projeto para Mono e Visual Studio.&lt;br /&gt;
&lt;h2&gt;30/05/2008&lt;/h2&gt;
Comecei a entender mais a fundo o projeto. Para isto, estudei HLSL e aprendi as principais diferen&amp;#231;as entre as duas linguagens.&lt;br /&gt;Portei o projeto para o Visual Studio 2008. E fiz uma an&amp;#225;lise do que j&amp;#225; foi feito e do que ainda faltava fazer.&lt;br /&gt;Acrescentei as &amp;quot;System-value semantics&amp;quot; &amp;#224; gramatica. Estas sem&amp;#226;nticas est&amp;#227;o dispon&amp;#237;veis apenas no &lt;a href="http://msdn.microsoft.com/en-us/library/bb509647(VS.85).aspx#System_Value" class="externalLink"&gt;Direct 3D 10&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;15/05/2008&lt;/h2&gt;O projeto &amp;#233; desenvolvido em C#. Como n&amp;#227;o conhecia a linguagem, aproveitei para aprender em um curso.&lt;br /&gt;&lt;br /&gt;Este curso faz parte do programa Students2Business, criado pela Microsoft e desenvolvido pelos Centros de Inova&amp;#231;&amp;#227;o e institui&amp;#231;&amp;#245;es de ensino parceiras. Resumidamente: o programa &amp;#233; gratu&amp;#237;to, o aluno pode escolher entre aulas de desenvolvimento ou de infra-estrutura de TI e &amp;#233; divido em 3 etapas. Ao final de cada etapa h&amp;#225; uma prova classificat&amp;#243;ria para a etapa seguinte. As etapas 2 e 3 possuem dura&amp;#231;&amp;#227;o de 40hs. Ao final da terceira etapa, os alunos que apresentarem os melhores projetos finais podem realizar gratuitamente provas de certifica&amp;#231;&amp;#227;o Microsoft e todos os alunos que concluirem as 3 etapas ter&amp;#227;o direito a participar do evento de formatura. Maiores informa&amp;#231;&amp;#245;es sobre o programa em &lt;a href="http://proform.msdnbrasil.tempsite.ws/public/Default.aspx" class="externalLink"&gt;http://proform.msdnbrasil.tempsite.ws/public/Default.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;30/04/2008&lt;/h2&gt;
Ol&amp;#225;!&lt;br /&gt;&lt;br /&gt;Me chamo B&amp;#225;rbara e entrei no projeto para substituir o Vitor, que se afastou para fazer doutorado. Como ele, vou utilizar este espa&amp;#231;o para periodicamente publicar os avan&amp;#231;os do projeto.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;21/03/2008&lt;/h2&gt;
Nesta semana terminei a separa&amp;#231;&amp;#227;o das fun&amp;#231;&amp;#245;es em arquivos diferentes e iniciei algumas convers&amp;#245;es de nomes de vari&amp;#225;veis de acordo com um contexto sem&amp;#226;ntico. &lt;br /&gt;&lt;br /&gt;Por exemplo, enquanto em HLSL temos: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void main(
        float4 position   : POSITION, 
        float3 normal      : NORMAL, 
	float2 uv : TEXCOORD0,
	float3 lightDir : TEXCOORD1,
	float3 eyeDir : TEXCOORD2,
	float3 spotDir : TEXCOORD3,
	float3 lightDir1 : TEXCOORD4,
	float3 spotDir1 : TEXCOORD5,
	float4 shadowUV1 : TEXCOORD6,
	float4 shadowUV2 : TEXCOORD7)
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Em GLSL teremos: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
varying vec3 tangentEyeDir;
varying vec3 tangentLightDir[2];
varying vec3 tangentSpotDir[2];
varying vec4 shadowUV[2]; 
void main() { ... }
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;uv, position e normal no HLSL seriam as vari&amp;#225;veis pr&amp;#233;-definidas gl_TexCoord[0], gl_Vertex e gl_Normal  no GLSL. &lt;br /&gt;
&lt;h2&gt;14/03/2008&lt;/h2&gt;
Nesta semana comecei a construir o separador de fun&amp;#231;&amp;#245;es. De um arquivo HLSL pode-se gerar v&amp;#225;rios GLSL. Para tal utilizo o grafo de depend&amp;#234;ncias das fun&amp;#231;&amp;#245;es declaradas no arquivo e em seus includes para separar as fun&amp;#231;&amp;#245;es corretamente, levando para o arquivo correto a formata&amp;#231;&amp;#227;o desejada e os coment&amp;#225;rios pertinentes a ela.  &lt;br /&gt;
&lt;h2&gt;07/03/2008&lt;/h2&gt;
Enquanto o HLSL permite v&amp;#225;rias entradas de execu&amp;#231;&amp;#227;o, ou seja, v&amp;#225;rias fun&amp;#231;&amp;#245;es main, o GLSL s&amp;#243; permite uma e exige o nome main. Desta forma, esta semana, trabalhei na cria&amp;#231;&amp;#227;o de um grafo de chamadas de fun&amp;#231;&amp;#245;es, para determinar quais fun&amp;#231;&amp;#245;es est&amp;#227;o sendo utilizadas para cada fun&amp;#231;&amp;#227;o de entrada no HLSL. Com esse grafo, poderei colocar cada fun&amp;#231;&amp;#227;o de entrada do HLSL em um arquivo diferente, levando tamb&amp;#233;m suas fun&amp;#231;&amp;#245;es dependentes. &lt;br /&gt;
&lt;h2&gt;29/02/2008&lt;/h2&gt;
Nesta semana trabalhei com a migra&amp;#231;&amp;#227;o da declara&amp;#231;&amp;#227;o de vari&amp;#225;veis uniform e varying, de uma fun&amp;#231;&amp;#227;o para o contexto do arquivo. &lt;br /&gt;&lt;br /&gt;Do HLSL:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void funcao(
    // parameters 
    float4 position,
    uniform float4 lightPosition, // object space 
    uniform float4x4 texViewProj2) {..}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para o GLSL &lt;br /&gt;&lt;pre&gt;
// parameters 
uniform float4 lightPosition; // object space 
uniform float4x4 texViewProj2;

void funcao(
     float4 position
) {..}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Migra&amp;#231;&amp;#227;o simples, mas trabalhosa quando se tem uma &amp;#225;rvore de Tokens sem ignorar espa&amp;#231;os, coment&amp;#225;rios, novas linhas e tabula&amp;#231;&amp;#245;es. Acabei tento muita dificuldade em identificar os coment&amp;#225;rios relevantes que deveriam ser movidos juntamente com o par&amp;#226;metro.&lt;br /&gt;
&lt;h2&gt;22/02/2008&lt;/h2&gt;
Ol&amp;#225; a todos. &lt;br /&gt;&lt;br /&gt;Neste espa&amp;#231;o vou publicar os avan&amp;#231;os do projeto semanalmente. &lt;br /&gt;&lt;br /&gt;Nesta &amp;#250;ltima semana testei a &lt;a href="http://OGRE" class="externalLink"&gt;http://www.ogre3d.org/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; como arquitetura para os testes do projeto. Ao converter shaders de HLSL para GLSL, &amp;#233; necess&amp;#225;rio tamb&amp;#233;m converter o c&amp;#243;digo fonte do programa que os usa, da API do DirectX para a da OpenGL. Esta parte n&amp;#227;o &amp;#233; coberta por este projeto, portanto &amp;#233; manual. &lt;br /&gt;&lt;br /&gt;A OGRE &amp;#233; uma engine que permite o uso de shaders HLSL, Cg e GLSL de maneira unificada, removendo os links diretos ao DirectX ou ao OpenGL. Usando-a, n&amp;#227;o perderemos tempo migrando o c&amp;#243;digo fonte dos testes, apenas com os testes dos shaders. &lt;br /&gt;&lt;br /&gt;Tamb&amp;#233;m desenvolvi uma parte do conversor: 
&lt;ol&gt;&lt;li&gt;A troca da fun&amp;#231;&amp;#227;o &amp;quot;mul&amp;quot; pelo &amp;quot;*&amp;quot;&lt;/li&gt;
&lt;li&gt;A invers&amp;#227;o de par&amp;#226;metros na fun&amp;#231;&amp;#227;o &amp;quot;cross&amp;quot;&lt;/li&gt;
&lt;li&gt;A remo&amp;#231;&amp;#227;o de par&amp;#226;metros na fun&amp;#231;&amp;#227;o &amp;quot;main&amp;quot;&lt;/li&gt;&lt;/ol&gt;
&lt;br /&gt;E estudei algumas propriedades da representa&amp;#231;&amp;#227;o de matrizes das duas linguagens. Apesar dos elementos descritos na p&amp;#225;gina &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Differences%20Between%20HLSL%20and%20GLSL&amp;referringTitle=Blog"&gt;Differences Between HLSL and GLSL&lt;/a&gt;, ainda tenho d&amp;#250;vidas sobre o modo de trabalho com as matrizes, especialmente se devo ou n&amp;#227;o transp&amp;#244;-las.  &lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Tue, 03 Nov 2009 18:57:21 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Blog 20091103065721P</guid></item><item><title>Updated Wiki: Blog</title><link>http://hl2glsl.codeplex.com/wikipage?title=Blog&amp;version=61</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Blog do Projeto&lt;/h1&gt;
Unfortunately this page exists only in portuguese. &lt;br /&gt;
&lt;h2&gt;03/11/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estive bastante envolvido com as tarefas acad&amp;#234;micas nos &amp;#250;ltimos dias, assim que n&amp;#227;o tenho tido muito tempo de postar aqui os resultados do meu trabalho.&lt;br /&gt;Encontrei um material muito bom sobre OpenCl aqui: &lt;a href="http://www.macresearch.org/opencl" class="externalLink"&gt;http://www.macresearch.org/opencl&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;, e assisti a todas as apresenta&amp;#231;&amp;#245;es. Nelas s&amp;#227;o apresentados desde quest&amp;#245;es gerais sobre opencl at&amp;#233; otimiza&amp;#231;&amp;#227;o de mem&amp;#243;ria.&lt;br /&gt;Ate,&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;05/10/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;gostaria de fazer aqui um pequeno post apenas para comentar sobre um benchmark que foi feito pela SiSoftware (os respons&amp;#225;veis pelo famoso Sandra).&lt;br /&gt;O benchmark levou em considera&amp;#231;&amp;#227;o as vers&amp;#245;es 2.2 e 2.3 do driver da NVidia, comparando CUDA e Opencl. Os resultados completos podem ser conferidos aqui: &lt;a href="http://sisoftware.co.uk/index.html?dir=qa&amp;amp;location=gpu_opencl&amp;amp;langx=en&amp;amp;a=" class="externalLink"&gt;http://sisoftware.co.uk/index.html?dir=qa&amp;amp;location=gpu_opencl&amp;amp;langx=en&amp;amp;a=&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;A id&amp;#233;ia central &amp;#233; que o OpenCl est&amp;#225; praticamente &amp;#224; altura do CUDA (tendo em vista os testes desse benchmark) em termos de desempenho, o que era uma grande cr&amp;#237;tica ao OpenCL.&lt;br /&gt;&lt;br /&gt;Att,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;02/10/09&lt;/h2&gt;Bom dia,&lt;br /&gt;estou postando aqui hoje meu primeiro tutorial sobre OpenCL. Esse primeiro tutorial pretende ser uma inicia&amp;#231;&amp;#227;o, um hello world detalhado de como funciona uma aplica&amp;#231;&amp;#227;o OpenCl.&lt;br /&gt;Futuros tutoriais aprofundar-se-&amp;#227;o em outros temas;&lt;br /&gt;O tutorial pode ser encontrado aqui: &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=OpenCl%20Tutorials%20-%201&amp;referringTitle=Blog"&gt;OpenCl Tutorials - 1&lt;/a&gt;;&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;30/09/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;queria avisar que a nvidia liberou para a comunidade em geral o driver da vers&amp;#227;o 1.0 do OpenCL nesta segunda feira.&lt;br /&gt;A p&amp;#225;gina com informa&amp;#231;&amp;#245;es para download tanto de windows, linux e mac pode ser encontrada aqui: &lt;a href="http://www.nvidia.com/object/cuda_opencl.html" class="externalLink"&gt;http://www.nvidia.com/object/cuda_opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/09/09&lt;/h2&gt;Bom dia,&lt;br /&gt;Nessa &amp;#250;ltima semana fiz uma pequena apresenta&amp;#231;&amp;#227;o sobre o projeto, apresentando todas as suas fases. Disponibilizo aqui apresenta&amp;#231;&amp;#227;o com &amp;#225;udio &lt;a href="http://www.inf.ufrgs.br/~lpchatain/apresentacao_chatain.pptx" class="externalLink"&gt;http://www.inf.ufrgs.br/~lpchatain/apresentacao_chatain.pptx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;(~14mb) (o Microsoft Office 2007 &amp;#233; necess&amp;#225;rio para abrir a apresenta&amp;#231;&amp;#227;o, um plugin de compatibilidade para vers&amp;#245;es anteriores do Office pode ser encontrada aqui: &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=941b3470-3ae9-4aee-8f43-c6bb74cd1466&amp;amp;displaylang=en" class="externalLink"&gt;http://www.microsoft.com/downloads/details.aspx?familyid=941b3470-3ae9-4aee-8f43-c6bb74cd1466&amp;amp;displaylang=en&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;);&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;14/09/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;nesta &amp;#250;ltima semana estive tentando fazer um benchmark do Cuda. Trata-se de um programa que resolve o problema das n-rainhas*, desenvolvido em Cuda e C&lt;u&gt;&lt;/u&gt;. O trabalho em quest&amp;#227;o foi feito pelo Vitor, e pode ser conferido em &lt;a href="http://vitorpamplona.com/wiki/An%C3%A1lise%20de%20Performance:%20C%20vs%20Cuda" class="externalLink"&gt;http://vitorpamplona.com/wiki/An%C3%A1lise%20de%20Performance:%20C%20vs%20Cuda&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;Nesse trabalho foi concluido que a implementa&amp;#231;&amp;#227;o em C&lt;u&gt;&lt;/u&gt; estava mais eficiente que a em Cuda. Entretanto fora utilizada a vers&amp;#227;o 1.0 do Cuda, e minha inten&amp;#231;&amp;#227;o era fazer um novo teste com a nova vers&amp;#227;o do compilador, para verificar eventuais melhorias de performance. Tamb&amp;#233;m gostaria de fazer os testes com diferentes configura&amp;#231;&amp;#245;es de hardware.&lt;br /&gt;Entretanto estive com bastantes dificuldades em fazer os testes funcionarem. Eles apresentaram um comportamento an&amp;#244;malo (leia-se imprevis&amp;#237;vel) na m&amp;#225;quina em que iniciei os testes, e atribui o problema &amp;#224; arquitetura 64bits da nova m&amp;#225;quina. Mudando para um processador 32 bits n&amp;#227;o tenho problemas com a compila&amp;#231;&amp;#227;o, entretanto estou tendo problemas com os kernels, que falham em sua execu&amp;#231;ao. Acredito ser um pequeno problema com a mudan&amp;#231;a do compilador (1.0 -&amp;gt; 2.2), mas ainda n&amp;#227;o consegui identific&amp;#225;-lo.&lt;br /&gt;Estarei postando aqui em breve um relat&amp;#243;rio de meus testes.&lt;br /&gt;&lt;br /&gt;Fora isso continuo estudando OpenCl, o que &amp;#233; bastante parecido com Cuda, assim que vou 'com as duas ao mesmo tempo'.&lt;br /&gt;&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;28/08/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estive estudando uma maneira de gerenciar automaticamente a inclus&amp;#227;o da DLL (como citado no post anterior). Postei algumas perguntas no blog da MSDN e obtive algumas respostas interessantes, que devem ser testadas nos proximos dias.&lt;br /&gt;&lt;br /&gt;Estive tamb&amp;#233;m estudando nessas &amp;#250;ltimas semanas &lt;b&gt;OpenCl&lt;/b&gt;.&lt;br /&gt;OpenCl &amp;#233; uma linguagem inicialmente criada pela Apple - e que teve como colaboradores a Intel, a nVidia e a AMD - para escrever programas que executem em ambientes heterogeneos, compostos de GPUs e CPUs.&lt;br /&gt;A linguagem foi 'abra&amp;#231;ada' pelo Kronos Group, que disponibilizou recentemente a especifica&amp;#231;&amp;#227;o da vers&amp;#227;o 1.0.&lt;br /&gt;Atualmente existem apenas vers&amp;#245;es beta dos drivers (visto que o kronos group somente disponibiliza a especifica&amp;#231;&amp;#227;o, cabe &amp;#224;s fabricantes de hardware gr&amp;#225;fico implementarem essa especifica&amp;#231;&amp;#227;o e fornecerem um compilador e um driver/sdk.&lt;br /&gt;&lt;br /&gt;Eu estou aqui testando com o driver beta da nvidia (apenas para desenvolvedores registrados). A implementa&amp;#231;&amp;#227;o da nVidia nada mais &amp;#233; que um 'mapeamento' da arquitetura CUDA para o OpenCl (creio que isso seja pr&amp;#243;ximo ao que a AMD/ATI est&amp;#225; fazendo, mapeando n&amp;#227;o para o CUDA mas para o Stream).&lt;br /&gt;&lt;br /&gt;Em CUDA, as fun&amp;#231;&amp;#245;es que se utilizam do paralelismo da GPU s&amp;#227;o conhecidas como &lt;i&gt;kernels&lt;/i&gt;.&lt;br /&gt;Kernels s&amp;#227;o executados por Streaming Multiprocessors (SMs). Cada SM, por sua vez, &amp;#233; composto por 8 Scalar Processors (SPs), os quais podem, cada um, executar simultaneamente at&amp;#233; 4 threads. Assim temos que um Streaming Multiprocessor pode executar simultaneamente at&amp;#233; 32 threads, o que chamaremos de &lt;i&gt;warp&lt;/i&gt;.&lt;br /&gt;Sempre que invocamos um kernel, especificamos para ele quantos &lt;i&gt;thread&lt;/i&gt; &lt;i&gt;blocks&lt;/i&gt; e quantas &lt;i&gt;threads&lt;/i&gt; &lt;i&gt;per&lt;/i&gt; &lt;i&gt;block&lt;/i&gt; queremos que esse kernel utilize. Cada SM encarrega-se da execu&amp;#231;&amp;#227;o de 1 thread block.&lt;br /&gt;Teoricamente, assim, se tivermos menos que 32 threads em um thread block estaremos 'perdendo processamento', pois n&amp;#227;o teremos preenchido o warp do SM. Se tivermos mais que 32 threads per block, entretanto, nossa situa&amp;#231;&amp;#227;o depender&amp;#225; da quantidade de mem&amp;#243;ria e de registradores que estar&amp;#227;o sendo utilizados. Funciona da seguinte forma: a CPU utiliza cache para esconder a latencia de mem&amp;#243;ria, i.e. para n&amp;#227;o termos que esperar sempre que os dados cheguem, n&amp;#243;s armazenamos-nos em uma cache. Na GPU escondemos a lat&amp;#234;ncia da mem&amp;#243;ria com computa&amp;#231;&amp;#245;es. Temos que a troca de contexto entre threads &amp;#233; muito veloz, assim ao inv&amp;#233;s de armazenarmos a mem&amp;#243;ria em uma grande cache, simplesmente mandamos outra thread executar enquanto esperamos, contanto que haja registradores livres no banco de registradores do SM.&lt;br /&gt;&lt;br /&gt;Em OpenCl temos a no&amp;#231;&amp;#227;o de &lt;i&gt;work-item&lt;/i&gt;s, que s&amp;#227;o mapeados para CUDA Threads, temos a no&amp;#231;&amp;#227;o de &lt;i&gt;work-groups&lt;/i&gt;, que s&amp;#227;o mapeados para thread blocks e por fim temos um NDRange, que &amp;#233; mapeado para um grid de thread blocks.&lt;br /&gt;O mapeamento &amp;#233; feito compilando OpenCl para o mesmo &amp;quot;bytecode&amp;quot;: PTX.&lt;br /&gt;&lt;br /&gt;Em breve estarei postando aqui trechos iniciais de c&amp;#243;digo em OpenCl, e espero estar fazendo alguns benchmarks com CUDA/OpenCl/CPU.&lt;br /&gt;&lt;br /&gt;Para maiores informa&amp;#231;&amp;#245;es a respeito das duas linguagens:
&lt;ul&gt;&lt;li&gt;Cuda:
&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.nvidia.com/object/cuda_home.html#" class="externalLink"&gt;http://www.nvidia.com/object/cuda_home.html#&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/CUDA" class="externalLink"&gt;http://en.wikipedia.org/wiki/CUDA&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ddj.com/hpc-high-performance-computing/207200659" class="externalLink"&gt;http://www.ddj.com/hpc-high-performance-computing/207200659&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;OpenCl
&lt;ul&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/OpenCL" class="externalLink"&gt;http://en.wikipedia.org/wiki/OpenCL&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.khronos.org/opencl/" class="externalLink"&gt;http://www.khronos.org/opencl/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.nvidia.com/object/cuda_opencl.html" class="externalLink"&gt;http://www.nvidia.com/object/cuda_opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ati.amd.com/technology/streamcomputing/opencl.html" class="externalLink"&gt;http://ati.amd.com/technology/streamcomputing/opencl.html&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.openclworld.com/" class="externalLink"&gt;http://www.openclworld.com/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;At&amp;#233; mais,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/07/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;Nesta semana estive com alguns problemas relativos &amp;#224; compatibilidade do debugger quando o projeto &amp;#233; levado a outros computadores. Esses problemas se deveram n&amp;#227;o &amp;#224; falta de compatibilidade do programa, mas sim do Package. Corrigi o problema, mas pretendo investigar a sua causa.&lt;br /&gt;Estou agora precisando ter acesso ao executavel gerado ap&amp;#243;s a compila&amp;#231;&amp;#227;o, estive dando uma olhada nisso nesta semana, sem muito sucesso. Al&amp;#233;m disso, preciso encontrar uma forma de manter sempre a DLL modificada como a acessivel pelo programa, ou seja, preciso de alguma forma manter a dll nas pastas do Visual Studio, no local onde o Package &amp;#233; instalado, e fazer com que tudo isso se ajeite na hora da instala&amp;#231;&amp;#227;o do pacote.&lt;br /&gt;Al&amp;#233;m desses pequenos problemas, continuo trabalhando na parte gr&amp;#225;fica (infelizmente n&amp;#227;o sou muito proficiente na cria&amp;#231;&amp;#227;o de interfaces amig&amp;#225;veis e bonitas) para integr&amp;#225;-la bem ao ambiente do Visual Studio. Ainda estou pensando em uma boa forma de dispor os compontentes, e em como melhorar a usabilidade do debugger.&lt;br /&gt;Fora isso ele se encontra bem integrado. &amp;#201; preciso fazer alguns testes, nos quais me dedicarei na pr&amp;#243;xima semana.&lt;br /&gt;&lt;br /&gt;At&amp;#233; la,&lt;br /&gt;&lt;br /&gt;Leonardo&lt;br /&gt;
&lt;h2&gt;08/07/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;Estou fazendo atualmente alguns ajustes automatizar mais o debugger, utilizando para isso as interface IVsRunningDocTableEvents, que implementa alguns m&amp;#233;todos para obter as notifica&amp;#231;&amp;#245;es sobre modifica&amp;#231;&amp;#245;es na IDE.&lt;br /&gt;Para poder passar a receber os eventos da IDE (que ser&amp;#227;o tratados pelos handlers da interface, a saber:
&lt;ul&gt;&lt;li&gt;int IVsRunningDocTableEvents.OnAfterAttributeChange&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterDocumentWindowHide&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterFirstDocumentLock&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnAfterSave&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnBeforeDocumentWindowShow&lt;/li&gt;
&lt;li&gt;int IVsRunningDocTableEvents.OnBeforeLastDocumentUnlock&lt;/li&gt;&lt;/ul&gt;
)&lt;br /&gt;&lt;br /&gt;Esses eventos s&amp;#227;o importantes para que possamos ser notificados de modifica&amp;#231;&amp;#245;es importantes, como por exemplo saber quais s&amp;#227;o os documentos que est&amp;#227;o abertos.&lt;br /&gt;&lt;br /&gt;Para poder receber os eventos, devemos nos inscrever da seguinte forma:&lt;br /&gt;Declaramos inicialmente um cookie:
&lt;ul&gt;&lt;li&gt;uint cookie;&lt;/li&gt;&lt;/ul&gt;
E logo ap&amp;#243;s devemos declarar uma interface IVsRunningDocumentTable, e solicitar que ela avise sobre os eventos
&lt;ul&gt;&lt;li&gt;IVsRunningDocumentTable rdt = &lt;/li&gt;&lt;/ul&gt;
                (IVsRunningDocumentTable)Package.GetGlobalService(typeof(SVsRunningDocumentTable));
&lt;ul&gt;&lt;li&gt;rdt.AdviseRunningDocTableEvents(this, out dwCookie);&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Em breve, novas novidades.&lt;br /&gt;At&amp;#233;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;11/06/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;infelizemente, ap&amp;#243;s algum tempo de estudo em cima do debugger de exemplo, feito por Jackson Davis, dispon&amp;#237;vel em &lt;a href="http://code.msdn.microsoft.com/debugenginesample" class="externalLink"&gt;http://code.msdn.microsoft.com/debugenginesample&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;, e ap&amp;#243;s uma troca de e-mails com o mesmo, constatei que o desenvolvimento de uma debug engine para o VS, ou seja, o objetivo inicial de integrar totalmente o debugger de GLSL com o debugger do Visual Studio &amp;#233; demasiado complexa, visto que h&amp;#225; um grande n&amp;#250;mero de interfaces a implementar e que aparentemente o debugger de GLSL n&amp;#227;o &amp;#233; compat&amp;#237;vel com o modelo de debug engine que o Visual Studio espera. Com certeza ha uma maneira de realizar essa integra&amp;#231;ao, fazendo as devidas modifica&amp;#231;&amp;#245;es no debugger e implementando as interfaces requeridas pelo VS, mas esse trabalho levar&amp;#225; muito tempo.&lt;br /&gt;Portanto, dadas as condi&amp;#231;&amp;#245;es, optamos por desenvolver o depurador de forma externa ao depurador do Visual Studio, como j&amp;#225; vinha sendo feito em paralelo. Existe uma quantidade consideravel de melhorias que se podem fazer e &amp;#233; esse o atual objetivo.&lt;br /&gt;Tendo em vista o atual foco do trabalho, em pouco tempo espero estar postando alguns print screens e releases do debugger 'integrado'.&lt;br /&gt;&lt;br /&gt;Obrigado,&lt;br /&gt;&lt;br /&gt;Leonardo&lt;br /&gt;
&lt;h2&gt;26/05/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estou utilizando os objetos DTE e DTE2 para alguns testes. Ainda tive alguns problemas ap&amp;#243;s o &amp;#250;ltimo post para conseguir o objeto, mas agora essa j&amp;#225; &amp;#233; uma quest&amp;#227;o do passado.&lt;br /&gt;Estive nessas semanas estudando os objetos DTE e DTE2 e tamb&amp;#233;m estudando um projeto de exemplo de um depurador C&lt;u&gt;&lt;/u&gt; integrado ao Visual Studio. Os resultados desse estudo ainda n&amp;#227;o s&amp;#227;o vis&amp;#237;veis no depurador GLSL.&lt;br /&gt;Quanto a altera&amp;#231;oes no depurador, coloquei uma lista com os shaders sendo editados no projeto, de forma que o usu&amp;#225;rio possa escolher mais facilmente qual o shader a ser escolhido. Vou seguir com algumas altera&amp;#231;&amp;#245;es visuais desse estilo para deixar o debugger mais amig&amp;#225;vel.&lt;br /&gt;&lt;br /&gt;At&amp;#233;&lt;br /&gt;
&lt;h2&gt;12/05/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;ontem descobri uma solu&amp;#231;&amp;#227;o interessante para um pequeno problema que me atormentou por bastante tempo e que pelo visto atormenta bastante gente ainda.&lt;br /&gt;Para solucionar uma s&amp;#233;rie de quest&amp;#245;es ao desenvolver VSPackages, podemos utilizar o &amp;quot;automation object&amp;quot; DTE, que representa o objeto de mais alta hierarquia no ambiente EnvDTE, que possui referencias a todos os elementos da automa&amp;#231;&amp;#227;o do n&amp;#250;cleo do VS. Para tanto declaramos uma interface DTE, pertencente ao namespace EnvDTE (&amp;#233; necess&amp;#225;rio adicionar uma Reference ao projeto: EnvDTE), e utilizamos o m&amp;#233;todo GetService para recuperar o objeto DTE (ele ser&amp;#225; referenciado pela interface DTE que declaramos).&lt;br /&gt;Pretendo colocar mais explica&amp;#231;&amp;#245;es sobre o objeto DTE nos proximos post, mas agora quero me concentrar na explica&amp;#231;&amp;#227;o e solu&amp;#231;&amp;#227;o do problema que me atormentou.&lt;br /&gt;Eis que o seguinte c&amp;#243;digo &amp;#233; o respons&amp;#225;vel por declarar e recuperar o objeto DTE:&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; EnvDTE;

DTE dte;

&lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Initialize() {
&lt;span style="color:Green;"&gt;//Inicializa&amp;#231;&amp;#245;es&lt;/span&gt;

&lt;span style="color:Blue;"&gt;this&lt;/span&gt;.dte = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SDTE)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; DTE;
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Entretanto, ap&amp;#243;s a execu&amp;#231;&amp;#227;o do trecho, dte continuava sempre com valor null, o que acabava gerando exce&amp;#231;&amp;#245;es e obviamente n&amp;#227;o era o que deveria estar acontecendo.&lt;br /&gt;Buscando na internet, encontrei no VSX Team Blog (o blog do pessoal do VSX (Visual Studio Extensibility)) a solu&amp;#231;&amp;#227;o para meu problema.&lt;br /&gt;O fato &amp;#233; que caso o ambiente n&amp;#227;o esteja totalmente carregado (em &amp;quot;zombie state&amp;quot;), a solicita&amp;#231;&amp;#227;o da referencia do objeto DTE retorna null. Como eu queria que o package fosse carregado juntamente com o VS (no startup), a inicializa&amp;#231;&amp;#227;o do package ocorria antes de o ambiente estar totalmente carregado, e dte continha sempre o valor null.&lt;br /&gt;Assim, a solu&amp;#231;&amp;#227;o proposta pelo pessoal do blog &amp;#233; a seguinte: utilizar a interface IVsShellPropertyEvents, implementando o handler OnShellPropertyChange, o qual faz o tracking do estado da IDE. A propriedade que diz se o VS est&amp;#225; zombie &amp;#233; a VSPROPID_Zombie.&lt;br /&gt;Segue abaixo a implementa&amp;#231;&amp;#227;o do blog do pessoal do VSX:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
      DTE dte;
      &lt;span style="color:Blue;"&gt;uint&lt;/span&gt; cookie;
      &lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Initialize()
      {
           &lt;span style="color:Blue;"&gt;base&lt;/span&gt;.Initialize();
           IVsShell shellService = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsShell)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; IVsShell;
           &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (shellService != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
                ErrorHandler.ThrowOnFailure(shellService.AdviseShellPropertyChanges(&lt;span style="color:Blue;"&gt;this&lt;/span&gt;,&lt;span style="color:Blue;"&gt;out&lt;/span&gt; cookie));
           ...
        }

        &lt;span style="color:Blue;"&gt;#region&lt;/span&gt; IVsShellPropertyEvents Members

        &lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;int&lt;/span&gt; OnShellPropertyChange(&lt;span style="color:Blue;"&gt;int&lt;/span&gt; propid, &lt;span style="color:Blue;"&gt;object&lt;/span&gt; &lt;span style="color:Blue;"&gt;var&lt;/span&gt;)
        {
            &lt;span style="color:Green;"&gt;// when zombie state changes to false, finish package initialization&lt;/span&gt;
            &lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((&lt;span style="color:Blue;"&gt;int&lt;/span&gt;)__VSSPROPID.VSSPROPID_Zombie == propid)
            {
                &lt;span style="color:Blue;"&gt;if&lt;/span&gt; ((&lt;span style="color:Blue;"&gt;bool&lt;/span&gt;)&lt;span style="color:Blue;"&gt;var&lt;/span&gt; == &lt;span style="color:Blue;"&gt;false&lt;/span&gt;)
                {
                    &lt;span style="color:Green;"&gt;// zombie state dependent code&lt;/span&gt;
                    &lt;span style="color:Blue;"&gt;this&lt;/span&gt;.dte = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SDTE)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; DTE;
                    &lt;span style="color:Green;"&gt;// eventlistener no longer needed&lt;/span&gt;
                    IVsShell shellService = GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsShell)) &lt;span style="color:Blue;"&gt;as&lt;/span&gt; IVsShell;
                    &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (shellService != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
                        ErrorHandler.ThrowOnFailure(shellService.UnadviseShellPropertyChanges(&lt;span style="color:Blue;"&gt;this&lt;/span&gt;.cookie));
                    &lt;span style="color:Blue;"&gt;this&lt;/span&gt;.cookie = 0;
                }
            }

            &lt;span style="color:Blue;"&gt;return&lt;/span&gt; VSConstants.S_OK;

        }

        &lt;span style="color:Blue;"&gt;#endregion&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Esse artigo pode ser encontrado em &lt;a href="http://blogs.msdn.com/vsxteam/archive/2008/06/09/dr-ex-why-does-getservice-typeof-envdte-dte-return-null.aspx" class="externalLink"&gt;http://blogs.msdn.com/vsxteam/archive/2008/06/09/dr-ex-why-does-getservice-typeof-envdte-dte-return-null.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Nos proximos posts estarei descrevendo mais a fundo a parte t&amp;#233;cnica do VS que estudei at&amp;#233; agora, e introduzirei alguns dos problemas futuros que pretendo estar resolvendo.&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;06/05/09&lt;/h2&gt;Ol&amp;#225;,&lt;br /&gt;nestas ultimas semanas estive um pouco sobrecarregado, e n&amp;#227;o tive muito tempo para escrever no blog. A primeira etapa da depura&amp;#231;&amp;#227;o j&amp;#225; esta concluida, entretanto restam alguns bugs relativos ao depurador que devem ser resolvidos antes de ser lan&amp;#231;ado um release do plug-in.&lt;br /&gt;Venho trabalhando na parte mais profunda da integra&amp;#231;&amp;#227;o.&lt;br /&gt;Al&amp;#233;m da mera quest&amp;#227;o de mapear as funcionalidades do depurador para a IDE (que n&amp;#227;o &amp;#233; trivial), restam alguns problemas que surgem do fato de que algumas features existentes no VS n&amp;#227;o se encontram atualmente no depurador (como por exemplo a utiliza&amp;#231;&amp;#227;o de breakpoints). Essas funcionalidades dever&amp;#227;o ser implementadas em breve.&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;23/04/09&lt;/h2&gt;Oi,&lt;br /&gt;nesta semana finalizei uma primeira integra&amp;#231;&amp;#227;o. Neste primeiro est&amp;#225;gio temos, como j&amp;#225; foi dito, o depurador da B&amp;#225;rbara executando sobre o Visual Studio.&lt;br /&gt;H&amp;#225; ainda uma s&amp;#233;rie de melhorias que devem ser feitas sobre esta integra&amp;#231;&amp;#227;o:
&lt;ul&gt;&lt;li&gt;Melhorias na estrutura&amp;#231;&amp;#227;o e organiza&amp;#231;&amp;#227;o do c&amp;#243;digo;&lt;/li&gt;
&lt;li&gt;Remo&amp;#231;&amp;#227;o de alguns bugs;&lt;/li&gt;
&lt;li&gt;Melhor organiza&amp;#231;&amp;#227;o visual;&lt;/li&gt;&lt;/ul&gt;
At&amp;#233; o fim desta semana planejo ter uma vers&amp;#227;o utilizavel do depurador, melhor organizada visualmente, com algumas funcionalidades a mais (no que toca &amp;#224; integra&amp;#231;&amp;#227;o, por exemplo que o depurador saiba qual o shader que deve ser depurado automaticamente, assim como o programa opengl.&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;20/04/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;estou tendo alguns problemas na integra&amp;#231;&amp;#227;o, que derivam diretamente de d&amp;#250;vidas com rela&amp;#231;&amp;#227;o ao depurador desenvolvido pela Barbara.&lt;br /&gt;A id&amp;#233;ia desta primeira integra&amp;#231;&amp;#227;o &amp;#233; bastante simples, uma simples adi&amp;#231;&amp;#227;o do depurador da barbara sobre o VS. A id&amp;#233;ia &amp;#233; que ap&amp;#243;s essa etapa seja construido incrementalmente o depurador integrado. Nesse ponto temos algumas dificuldades, como por exemplo que o depurador n&amp;#227;o suporta a coloca&amp;#231;&amp;#227;o de breakpoints, mas executa sempre passo a passo, de forma que n&amp;#227;o se pode definir de forma mais flexivel o fluxo do programa.&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;10/04/09&lt;/h2&gt;Ol&amp;#225;,&lt;br /&gt;nesta semana estive trabalhando na efetiva integra&amp;#231;&amp;#227;o do Depurador GLSL para o VS2008. A id&amp;#233;ia inicial inserir apenas o depurador de forma externa ao depurador do Visual Studio, o que &amp;#233; uma tarefa mais simples e deve ser terminada at&amp;#233; o final da semana. Nos proximos posts estarei publicando screenshots e maiores explica&amp;#231;&amp;#245;es sobre essa integra&amp;#231;&amp;#227;o. Esse trabalho tem a vantagem de que o depurador estar&amp;#225; rapidamente pronto para ser utilizado, entretanto ele n&amp;#227;o estara integrado com o depurador do Visual Studio. Para acess&amp;#225;-lo haver&amp;#227;o menus e janelas exclusivas que se encarregar&amp;#227;o de realizar todo o processo.&lt;br /&gt;Ap&amp;#243;s terminar essa primeira etapa de integra&amp;#231;&amp;#227;o, pretendo construir uma Debug Engine que se comunique com a SDM e torne o processo de depura&amp;#231;&amp;#227;o transparente ao usu&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;01/04/09&lt;/h2&gt;Ol&amp;#225; a todos,&lt;br /&gt;nas semanas anteriores eu estive estudando o desenvolvimento de VSPackages gen&amp;#233;ricos, como uma forma de me familiarizar com eles. Nesta semana, e nas que vir&amp;#227;o, me voltei efetivamente para o VSDebugger e como extend&amp;#234;-lo.&lt;br /&gt;&lt;br /&gt;Basicamente o debugger do visual studio &amp;#233; composto de tr&amp;#234;s partes:
&lt;ul&gt;&lt;li&gt;Interface com o usu&amp;#225;rio (UI), que permite, por exemplo, que sejam colocados breakpoints, que o codigo seja executado instru&amp;#231;&amp;#227;o a instru&amp;#231;&amp;#227;o, etc.&lt;/li&gt;
&lt;li&gt;SDM (Session Debug Manager), que &amp;#233; basicamente quem gerencia as Debug Engines. Pode ser visto como um multiplexador de Debug Engines, al&amp;#233;m de fazer a comunica&amp;#231;&amp;#227;o com a UI. A SDM &amp;#233; implementada pelo VS e n&amp;#227;o ser&amp;#225; alterada.&lt;/li&gt;
&lt;li&gt;Debug Engine (DE), que &amp;#233; o elemento que efetivamente faz a depura&amp;#231;&amp;#227;o do programa, e se comunica com a SDM. &amp;#201; aqui que ser&amp;#225; introduzido o depurador de GLSL.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Assim, teremos que construir uma DE que incorpore o depurador desenvolvido pela B&amp;#225;rbara. Para construir uma DE, s&amp;#227;o necess&amp;#225;rios alguns passos:
&lt;ul&gt;&lt;li&gt;Primeiro devemos registrar nossa DE no Visual Studio, permitindo que ele a reconhe&amp;#231;a e utilize;&lt;/li&gt;
&lt;li&gt;Nossa DE deve, quando solicitado pela SDM, &amp;quot;conectar-se&amp;quot; ao programa a ser depurado. Isso ocorre quando o usu&amp;#225;rio escolhe depurar o programa. Ocorre ent&amp;#227;o uma troca de mensagens entre a SDM e as DEs;&lt;/li&gt;
&lt;li&gt;Agora que nossa DE est&amp;#225; &amp;quot;conectada&amp;quot; ao programa efetivamente podemos nos concentrar em depurar o programa. Esta etapa consiste em:
&lt;ul&gt;&lt;li&gt;Controlar o fluxo de execu&amp;#231;&amp;#227;o, respeitando breakpoints e execu&amp;#231;&amp;#227;o step-by-step;&lt;/li&gt;
&lt;li&gt;Comunicar-se com a SDM, fazendo com que tanto o VS quanto o usu&amp;#225;rio tenham um feedback da depura&amp;#231;&amp;#227;o;&lt;/li&gt;
&lt;li&gt;Al&amp;#233;m disso temos que permitir:
&lt;ul&gt;&lt;li&gt;A cria&amp;#231;&amp;#227;o/dele&amp;#231;&amp;#227;o de breakpoints;&lt;/li&gt;
&lt;li&gt;A inser&amp;#231;&amp;#227;o de watches;&lt;/li&gt;
&lt;li&gt;A visualiza&amp;#231;&amp;#227;o da pilha de chamadas;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;A seguir devemos nos desconectar do programa e solicitar &amp;#224; SDM para que o mesmo seja terminado;&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Neste momento estou estudando um pouco mais o trabalho da B&amp;#225;rbara. Minhas d&amp;#250;vidas se concentram em como exatamente integrar todo o sistema de debugging do Visual Studio ao depurador que j&amp;#225; foi desenvolvido. Nos pr&amp;#243;ximos posts procurarei explicar um pouco melhor o funcionamento do mecanismo de depura&amp;#231;&amp;#227;o do VS, al&amp;#233;m de tentar aproximar um pouco mais os dois debuggers.&lt;br /&gt;&lt;br /&gt;At&amp;#233; l&amp;#225;,&lt;br /&gt;Leonardo Chatain&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;25/03/09 - Hello World&lt;/h2&gt;Nesta semana continuei a estudar o desenvolvimento de um Package para o VS2008. O estudo foi dirigido basicamente aos procedimentos de cria&amp;#231;&amp;#227;o e ao funcionamento dos recursos gerados pelo wizard.&lt;br /&gt;&lt;br /&gt;Para iniciar o desenvolvimento de um VSPackage, ap&amp;#243;s baixar o SDK do Visual Studio, &amp;#233; utilizar o wizard de cria&amp;#231;&amp;#227;o de package, que se encarrega de gerar o c&amp;#243;digo base, deixando para n&amp;#243;s apenas o desenvolvimento do Package.&lt;br /&gt;Assim, ap&amp;#243;s definir o nome de nosso Package, somos perguntados a respeito de algumas coisas sobre o ele: a linguagem em que o desenvolveremos, se queremos uma Tool Window, um Menu Tool, etc.&lt;br /&gt;Para construir o Hello World utilizei C# e criei tanto uma Tool Window quanto um Menu Tool.&lt;br /&gt;Os resultados foram os seguintes:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Window&lt;/b&gt; &lt;b&gt;Tool:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63149" alt="windowTool.bmp" title="windowTool.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63150" alt="windowTool2.bmp" title="windowTool2.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo Fonte&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; okButton_Click(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, System.EventArgs e)
        {
            MessageBox.Show(&lt;span style="color:#A31515;"&gt;&amp;quot;Seu nome &amp;#233; &amp;quot;&lt;/span&gt; + nameBox.Text.ToString(), &lt;span style="color:#A31515;"&gt;&amp;quot;Seu nome&amp;quot;&lt;/span&gt;, MessageBoxButtons.OK);
        }

        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; limparButton_Click(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, System.EventArgs e)
        {
            nameBox.Text = &lt;span style="color:#A31515;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;;
        }

&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Command Tool:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=hl2glsl&amp;DownloadId=63151" alt="cmdTool.bmp" title="cmdTool.bmp" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo fonte do command:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
        &lt;span style="color:Blue;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; MenuItemCallback(&lt;span style="color:Blue;"&gt;object&lt;/span&gt; sender, EventArgs e)
        {
            &lt;span style="color:Green;"&gt;// Show a Message Box to prove we were here&lt;/span&gt;
            IVsUIShell uiShell = (IVsUIShell)GetService(&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SVsUIShell));
            Guid clsid = Guid.Empty;
            &lt;span style="color:Blue;"&gt;int&lt;/span&gt; result;
            Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(uiShell.ShowMessageBox(
                       0,
                       &lt;span style="color:Blue;"&gt;ref&lt;/span&gt; clsid,
                       &lt;span style="color:#A31515;"&gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;,
                       &lt;span style="color:Blue;"&gt;string&lt;/span&gt;.Format(CultureInfo.CurrentCulture, &lt;span style="color:#A31515;"&gt;&amp;quot;Hello World - Este &amp;#233; um menuTool&amp;quot;&lt;/span&gt;),
                       &lt;span style="color:Blue;"&gt;string&lt;/span&gt;.Empty,
                       0,
                       OLEMSGBUTTON.OLEMSGBUTTON_OK,
                       OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST,
                       OLEMSGICON.OLEMSGICON_INFO,
                       0,        &lt;span style="color:Green;"&gt;// false&lt;/span&gt;
                       &lt;span style="color:Blue;"&gt;out&lt;/span&gt; result));
        }
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Nos proximos posts estarei explicando com mais detalhes o funcionamento desses elementos. Atualmente estou buscando algo mais proximo do debugger, assim que possivelmente nos proximos posts n&amp;#227;o estarei mais lidando com exemplos gen&amp;#233;ricos, mas com algo mais focado no debugger em si.&lt;br /&gt;Uma &amp;#243;tima refer&amp;#234;ncia (em ingles) &amp;#233; &lt;a href="http://learnvsxnow.codeplex.com/" class="externalLink"&gt;http://learnvsxnow.codeplex.com/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;17/03/09&lt;/h2&gt;Oi pessoal,&lt;br /&gt;sou o Leonardo e este &amp;#233; meu primeiro post aqui.&lt;br /&gt;Atualmente, como a Barbara comentou, estou estudando o desenvolvimento de um &amp;quot;plug-in&amp;quot; para o Visual Studio, que permita a integra&amp;#231;&amp;#227;o do trabalho dela com o ambiente de desenvolvimento, facilitando assim o trabalho de depura&amp;#231;&amp;#227;o.&lt;br /&gt;A id&amp;#233;ia &amp;#233; tornar o depurador natural ao usu&amp;#225;rio do VS.&lt;br /&gt;&lt;br /&gt;O desenvolvimento se far&amp;#225; a partir de VSPackages, que s&amp;#227;o a ferramenta de extensibilidade mas completa que a Microsoft prov&amp;#234; para o Visual Studio.&lt;br /&gt;&lt;br /&gt;Mais informa&amp;#231;&amp;#245;es sobre Visual Studio Extensibility, al&amp;#233;m do download dos SDKs do VS2005 e VS208, podem ser encontradas aqui: &lt;a href="http://msdn.microsoft.com/en-us/vsx/default.aspx" class="externalLink"&gt;http://msdn.microsoft.com/en-us/vsx/default.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; (Visual Studio Extensibility Developer Center).&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;br /&gt;
&lt;h2&gt;08/03/2009&lt;/h2&gt;Nesta semana trabalhei corrigindo problemas na interface e procurei deixar o c&amp;#243;digo do depurador menos &amp;quot;duro&amp;quot;. Como por exemplo, poder abrir os arquivos em qualquer ordem e n&amp;#227;o primeiro um tipo de shader e depois o outro.&lt;br /&gt;
&lt;h2&gt;24/02/2009&lt;/h2&gt;Em virtude da troca de bolsistas, optamos por focar no desenvolvimento do plugin para o Visual Studio. Desta forma, o Leonardo est&amp;#225; estudando o desenvolvimento de plugins, enquanto eu estou arrumando o c&amp;#243;digo para que esta integra&amp;#231;&amp;#227;o possa ser feita.&lt;br /&gt;
&lt;h2&gt;18/02/2009&lt;/h2&gt;Fui aprovada para o Mestrado em Ci&amp;#234;ncia da Computa&amp;#231;&amp;#227;o - UFRGS, desta forma, a partir de mar&amp;#231;o estarei afastada do projeto. Quem ir&amp;#225; dar continuidade ao projeto &amp;#233; o aluno no quinto semestre de gradua&amp;#231;&amp;#227;o do curso de &lt;br /&gt;Ci&amp;#234;ncia da Computa&amp;#231;&amp;#227;o - UFRGS, Leonardo Chatain. Seja bem vindo, Leonardo!&lt;br /&gt;
&lt;h2&gt;18/01/2009&lt;/h2&gt;Como disse no &amp;#250;ltimo post, comecei a trabalhar na integra&amp;#231;&amp;#227;o da ferramenta com outras. &lt;br /&gt;A ferramenta com a qual estou fazendo integra&amp;#231;&amp;#227;o &amp;#233; a Shader Designer. A principal dificuldade encontrada at&amp;#233; o momento est&amp;#225; sendo portar o projeto da Shader Designer do Microsoft Visual Studio 2003 para o 2008 (ambiente em que foi desenvolvido o depurador). Estou tendo que re-escrever praticamente todo o c&amp;#243;digo. Al&amp;#233;m de que, o Shader Designer utiliza uma s&amp;#233;rie de c&amp;#243;digos fontes e de bibliotecas de terceiros (vide abaixo) que tamb&amp;#233;m est&amp;#227;o sendo portados. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digos Fontes de terceiros&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;a) 3DLabs GLSL Open Source Compiler &lt;br /&gt;&lt;br /&gt;b) Algumas fun&amp;#231;&amp;#245;es da &amp;quot;Matrix and Quaternion fAQ&amp;quot; &lt;br /&gt;&lt;br /&gt;c) AVI exporter &lt;br /&gt;&lt;br /&gt;d) GLEW Extensions manager.&lt;br /&gt;&lt;br /&gt;e) MeshMender da Nvidia&lt;br /&gt;&lt;br /&gt;f) DEV-IL&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Bibliotecas de terceiros&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;a) Compona's SyntaxBox. &lt;br /&gt;&lt;br /&gt;b) Flexporter&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;15/12/2008&lt;/h2&gt;Nestas &amp;#250;ltimas semanas escrevi e apresentei um trabalho acad&amp;#234;mico sobre o assunto. A apresenta&amp;#231;&amp;#227;o pode ser obtida &lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=51900';"&gt;aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Tamb&amp;#233;m foram acrescentadas novas funcionalidades:
&lt;ul&gt;&lt;li&gt;Permite ao usu&amp;#225;rio optar por depurar:
&lt;ul&gt;&lt;li&gt;Apenas o shader;&lt;/li&gt;
&lt;li&gt;Apenas o programa OpenGL hospedeiro;&lt;/li&gt;
&lt;li&gt;Ambos.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;ul&gt;&lt;li&gt;Permite visualizar o valor atualizado das vari&amp;#225;veis que j&amp;#225; foram depuradas&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Nas pr&amp;#243;ximas semanas, vou iniciar o estudo sobre desenvolvimento de plugins e come&amp;#231;ar a integra&amp;#231;&amp;#227;o da ferramenta.&lt;br /&gt;
&lt;h2&gt;30/11/2008&lt;/h2&gt;Como dito no post anterior, foram muitas as dificuldades encontradas na utiliza&amp;#231;&amp;#227;o de extens&amp;#245;es para captura de dados da placa gr&amp;#225;fica.&lt;br /&gt;Para que outras pessoas que necessitem utilizar estas extens&amp;#245;es n&amp;#227;o enfrentem o mesmo problema (principalmente pela falta de documenta&amp;#231;&amp;#227;o e de exemplos de uso), coloquei na p&amp;#225;gina &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Capturing%20Data%20From%20Graphics%20Hardware&amp;referringTitle=Blog"&gt;Capturing Data From Graphics Hardware&lt;/a&gt;, uma explica&amp;#231;&amp;#227;o das extens&amp;#245;es utilizadas com exemplos. &lt;br /&gt;&lt;br /&gt;O depurador foi aprimorado. Agora &amp;#233; poss&amp;#237;vel n&amp;#227;o apenas ver o resultado da vari&amp;#225;vel que est&amp;#225; sendo depurada, mas tamb&amp;#233;m das fun&amp;#231;&amp;#245;es pr&amp;#233;-definidas da OpenGL Al&amp;#233;m disto, foi escrito um trabalho acad&amp;#234;mico sobre o assunto, que ap&amp;#243;s sua apresenta&amp;#231;&amp;#227;o, tamb&amp;#233;m estar&amp;#225; dispon&amp;#237;vel aqui no CodePlex.&lt;br /&gt;&lt;br /&gt;Em breve tamb&amp;#233;m estarei disponibilizando um realease do depurador.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;30/10/2008 - Finishing the Debugger&lt;/h2&gt;Durante este m&amp;#234;s me foquei em terminar o depurador GLSL.&lt;br /&gt;Foram muitas as dificuldades encontradas, principalmente na utiliza&amp;#231;&amp;#227;o de extens&amp;#245;es para capturar a sa&amp;#237;da dos processadores de v&amp;#233;rtices e de fragmentos.&lt;br /&gt;Foram implementados 3 m&amp;#243;dulos:
&lt;ul&gt;&lt;li&gt;Wrapper OpenGL -&amp;gt; respons&amp;#225;vel por capturar as opera&amp;#231;&amp;#245;es OpenGL realizadas pelo programa OpenGL hospedeiro e inserir os c&amp;#243;digos necess&amp;#225;rios para depura&amp;#231;&amp;#227;o;&lt;/li&gt;
&lt;li&gt;Parser GLSL -&amp;gt; respons&amp;#225;vel por re-escrever o c&amp;#243;digo do shader GLSL de modo a inserir as vari&amp;#225;veis de depura&amp;#231;&amp;#227;o necess&amp;#225;rias&lt;/li&gt;
&lt;li&gt;Interfce Gr&amp;#225;fica -&amp;gt; respons&amp;#225;vel por interligar e utilizar os resultados obtidos nos demais m&amp;#243;dulos, al&amp;#233;m de, &amp;#233; claro, ser a interface com o usu&amp;#225;rio.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Este trabalho foi apresentado no &lt;a href="http://www.propesq.ufrgs.br/sic2008/index.htm" class="externalLink"&gt;XX Sal&amp;#227;o de IC - UFRGS&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. A apresenta&amp;#231;&amp;#227;o pode ser baixada &lt;a href="javascript:window.location.href='http://hl2glsl.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=47908';"&gt;aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Para as pr&amp;#243;ximas semanas pretendo continuar trabalhando no aprimoramento da ferramenta e escrever um documento mais detalhado sobre seu desenvolvimento.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;30/09/2008 - GLSL Debugger&lt;/h2&gt;
Passei algum tempo sem postar no blog. Durante este tempo estava trabalhando em uma nova etapa do projeto, o desenvolvimento de um plugin de depura&amp;#231;&amp;#227;o de GLSL para o Visual Studio. Maiores detalhes do andamento e da descri&amp;#231;&amp;#227;o desta etapa podem ser encontrados em &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=GLSL%20Debugger&amp;referringTitle=Blog"&gt;GLSL Debugger&lt;/a&gt;.&lt;br /&gt;
&lt;h2&gt;18/08/2008&lt;/h2&gt;GLSL n&amp;#227;o possui suporte &amp;#224; cast impl&amp;#237;cito (ex: vec4 color = 0.5;) assim, acrescentei o cast explicito (ex: vec4 color = vec4(0.5); )&lt;br /&gt;&lt;br /&gt;Continuei com os testes do programa. A principal dificuldade encontrada nos testes &amp;#233; a valida&amp;#231;&amp;#227;o. Por enquanto, o m&amp;#233;todo utilizado para os testes consiste em pegar um c&amp;#243;digo HLSL v&amp;#225;lido, converter e testar em um compilador GLSL se o c&amp;#243;digo gerado &amp;#233; v&amp;#225;lido ou n&amp;#227;o. Se n&amp;#227;o for, o programa &amp;#233; corrigido. Ou seja, por falta de uma BNF oficial da HLSL, nossos testes s&amp;#227;o baseados em exemplos. O que n&amp;#227;o &amp;#233; o ideal. A id&amp;#233;ia &amp;#233; que a pr&amp;#243;xima etapa de testes seja realizada comparando as imagens geradas. Ou seja, ser&amp;#227;o obtidas imagens executando o shader HLSL e estas ser&amp;#227;o comparadas com as imagens obtidas atrav&amp;#233;s da execu&amp;#231;&amp;#227;o do shader GLSL. A diferen&amp;#231;a entre estas imagens nos dir&amp;#225; o percentual de erro obtido na convers&amp;#227;o. &amp;#201; mais uma forma de validar o programa, por&amp;#233;m, o fato dos testes serem baseados em exemplos persiste. Para que este fator n&amp;#227;o seja t&amp;#227;o relevante, estamos utilizando uma gama variada de exemplos.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;04/08/2008&lt;/h2&gt;Como o programa estava dispon&amp;#237;vel apenas em vers&amp;#245;es de linha de comando, desenvolvi uma vers&amp;#227;o que apresenta uma interface gr&amp;#225;fica simplificada. Com esta interface, basta o usu&amp;#225;rio carregar o c&amp;#243;digo HLSL e clicar em converter. Os c&amp;#243;digos s&amp;#227;o exibidos lado &amp;#224; lado, facilitando a visualiza&amp;#231;&amp;#227;o pelo usu&amp;#225;rio.&lt;br /&gt;&lt;br /&gt;Esta interface apresenta um limitante, que &amp;#233; o fato de ser compat&amp;#237;vel apenas com sistemas Windows. Por&amp;#233;m, em breve, pretendo desenvolver uma vers&amp;#227;o compat&amp;#237;vel com outros sistemas.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;24/07/2008&lt;/h2&gt;GLSL n&amp;#227;o apresenta suporte ao comando &amp;quot;Switch&amp;quot;. Desta forma, fiz uma fun&amp;#231;&amp;#227;o que substitui este comando por &amp;quot;If..else&amp;quot;.&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;        switch ( teste ) {
    			case 0: k++; return teste; 
    			case 1: return teste; 
    			case 2: t++; return teste; 
    			default: { 
    				teste++;
       			} 
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;      if (teste == 0) { k++; return teste; }
      else if (teste == 1) { return teste;}
      else if (teste == 2) { t++; return teste; }
      else { teste++;  }
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;GLSL n&amp;#227;o permite atribui&amp;#231;&amp;#245;es para elementos dos vetores, se estes vetores forem vari&amp;#225;veis to tipo &amp;quot;varying&amp;quot;. Ent&amp;#227;o, fiz uma fun&amp;#231;&amp;#227;o que cria uma vari&amp;#225;vel tempor&amp;#225;ria, efetua a atribui&amp;#231;&amp;#227;o e ent&amp;#227;o atribui o valor &amp;#224; vari&amp;#225;vel original.&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;  float4 MyShader( float2 Tex : TEXCOORD0 ) : COLOR0
{
    float4 Color;
    
    Color = float4(1.0,1.0,1.0,1.0);
    Color.a;
    Color.a = 0.1;
    Color.rgb = float3(0.5f);

    Tex.y = Tex.y + (sin(timeraslow)*0.01);
    Tex.x = Tex.x + (cos(timeraslow)*0.01);
    Color = tex2D( g_samSrcColor, Tex.xy);

    Color -= tex2D( g_samSrcColor, Tex.xy-0.001)*2.0f;
    Color += tex2D( g_samSrcColor, Tex.xy+0.001)*2.0f;
    Color.rgb = float3((Color.r+Color.g+Color.b)/3.0f);   	
   	
    return Color;
}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Exemplo:  &lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;pre&gt; varying vec2 Tex;

void main( )
{
    vec4 Color;
    
    Color = vec4(1.0,1.0,1.0,1.0);
    Color.a;
    Color.a = 0.1;
    Color.rgb = vec3(0.5); //n&amp;#227;o necessita de vari&amp;#225;vel tempor&amp;#225;ria pois n&amp;#227;o &amp;#233; varying

    vec2 tempTex = Tex; //como Tex era varying foi criada uma vari&amp;#225;vel tempor&amp;#225;ria 

    tempTex.y = Tex.y + (sin(timeraslow)*0.01);
    Tex=tempTex;
    tempTex.x = Tex.x + (cos(timeraslow)*0.01);
    Tex=tempTex;
    Color = tex2D( g_samSrcColor, Tex.xy);

    Color -= tex2D( g_samSrcColor, Tex.xy-0.001)*2.0;
    Color += tex2D( g_samSrcColor, Tex.xy+0.001)*2.0;
    Color.rgb = vec3((Color.r+Color.g+Color.b)/3.0));   	
   	
    gl_FragColor = Color;
}
&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;09/07/2008&lt;/h2&gt;Acrescentei a convers&amp;#227;o das fun&amp;#231;&amp;#245;es intr&amp;#237;nsicas. Para as fun&amp;#231;&amp;#245;es intr&amp;#237;nsicas de HLSL que n&amp;#227;o s&amp;#227;o suportadas pela GLSL (vide &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Differences%20Between%20HLSL%20and%20GLSL&amp;referringTitle=Blog"&gt;Differences Between HLSL and GLSL&lt;/a&gt;), &amp;#233; emitida uma mensagem de aviso ao usu&amp;#225;rio.  GLSL tamb&amp;#233;m n&amp;#227;o suporta a letra 'f' ap&amp;#243;s um n&amp;#250;mero do tipo float (ex: 1.0f), ent&amp;#227;o, inseri uma fun&amp;#231;&amp;#227;o que remove este 'f' do n&amp;#250;mero. &lt;br /&gt;&lt;br /&gt;Iniciei tamb&amp;#233;m a fase de testes do programa. Para isto estou utilizando os shaders  &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Parsing%20Shaders&amp;referringTitle=Blog"&gt;Parsing Shaders&lt;/a&gt;. Ap&amp;#243;s converter, executo o arquivo gerado no software &lt;a href="http://www.opengl.org/sdk/tools/ShaderDesigner" class="externalLink"&gt;Shader Designer&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;. Este software &amp;#233; um editor/compilador de GLSL. Assim, atrav&amp;#233;s de sua sa&amp;#237;da, posso verificar se o c&amp;#243;digo GLSL gerado &amp;#233; v&amp;#225;lido ou n&amp;#227;o e corrigir os problemas encontrados.&lt;br /&gt;&lt;br /&gt;A vers&amp;#227;o mais atual dos fontes do projeto encontra-se &lt;a href="http://www.codeplex.com/hl2glsl/SourceControl/ListDownloadableCommits.aspx" class="externalLink"&gt;dispon&amp;#237;vel&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;04/07/2008&lt;/h2&gt;Fiz algumas altera&amp;#231;&amp;#245;es na gram&amp;#225;tica e acrescentei novas fun&amp;#231;&amp;#245;es para tratar estas altera&amp;#231;&amp;#245;es.&lt;br /&gt;&lt;br /&gt;Altera&amp;#231;&amp;#245;es na gram&amp;#225;tica:&lt;br /&gt;*Reconhecimento do par&amp;#226;metro &amp;quot;: Register&amp;quot;;&lt;br /&gt;*Reconhecimento do par&amp;#226;metro &amp;quot;: Packoffset&amp;quot;;&lt;br /&gt;*Reconhecimento do operador un&amp;#225;rio &amp;quot;!&amp;quot;;&lt;br /&gt;*Reconhecimento do tipo &amp;quot;uint&amp;quot;.&lt;br /&gt;&lt;br /&gt;GLSL n&amp;#227;o apresenta suporte para acesso &amp;#224; registradores. Assim, os par&amp;#226;metros &amp;quot;register&amp;quot; e &amp;quot;packoffset&amp;quot; n&amp;#227;o podem ser utilizados. A medida adotada para solucionar este problema &amp;#233; avisar ao usu&amp;#225;rio deste fato e perguntar se ele deseja remover estes par&amp;#226;metros. Caso ele opte por n&amp;#227;o remover, um aviso de que o c&amp;#243;digo gerado ser&amp;#225; inconsistente &amp;#233; emitido.&lt;br /&gt;&lt;br /&gt;O caso do tipo &amp;quot;uint&amp;quot; &amp;#233; similar, pois tamb&amp;#233;m n&amp;#227;o &amp;#233; suportado pela GLSL. S&amp;#243; que ao inv&amp;#233;s de remover a vari&amp;#225;vel, a op&amp;#231;&amp;#227;o dada ao usu&amp;#225;rio &amp;#233; a de troc&amp;#225;-lo pelo tipo int. &lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;18/06/2008&lt;/h2&gt;Passei a utilizar o Source Code Client do CodePlex para disponibilizar o c&amp;#243;digo fonte.&lt;br /&gt;&lt;br /&gt;Acrescentei as fun&amp;#231;&amp;#245;es para tratar &amp;quot;return&amp;quot; e o tipo da fun&amp;#231;&amp;#227;o &amp;quot;main&amp;quot;.&lt;br /&gt;&lt;br /&gt;Em GLSL &amp;#233; necess&amp;#225;rio uma fun&amp;#231;&amp;#227;o void main() que &amp;#233; de onde iniciar&amp;#225; a execu&amp;#231;&amp;#227;o.  Em HLSL, isto n&amp;#227;o &amp;#233; necess&amp;#225;rio.&lt;br /&gt;Assim, &amp;#233; preciso substituir o nome da fun&amp;#231;&amp;#227;o em HLSL por &amp;quot;main&amp;quot; e o tipo da fun&amp;#231;&amp;#227;o por void. O tipo da fun&amp;#231;&amp;#227;o deve ser salvo pois ele ser&amp;#225; utilizado na sa&amp;#237;da da fun&amp;#231;&amp;#227;o.  &lt;br /&gt;&lt;br /&gt;Como a fun&amp;#231;&amp;#227;o em GLSL &amp;#233; do tipo void, ela n&amp;#227;o tem mais o &amp;quot;return&amp;quot;.  Sua sa&amp;#237;da vai ser determinada de acordo com o tipo e os par&amp;#226;metros sem&amp;#226;nticos da fun&amp;#231;&amp;#227;o original, &lt;br /&gt;&lt;br /&gt;Ex: &lt;b&gt;C&amp;#243;digo HLSL&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;float4 pixelShader( float4 color):COLOR
{
          float4 teste =float4(0,1,0,0);
          float4 tes   = color + teste;

          return tes;
} &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C&amp;#243;digo GLSL&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;varying vec4 color;

void main() { 

	vec4 teste = vec4(0,1,0,0);
	vec4 tes   = color + teste;
	
	gl_FragColor = vec4(tes) ;  
} &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;02/06/2008&lt;/h2&gt;
Disponibilizei os fontes em desenvolvimento do projeto na sess&amp;#227;o Releases nas vers&amp;#245;es de projeto para Mono e Visual Studio.&lt;br /&gt;
&lt;h2&gt;30/05/2008&lt;/h2&gt;
Comecei a entender mais a fundo o projeto. Para isto, estudei HLSL e aprendi as principais diferen&amp;#231;as entre as duas linguagens.&lt;br /&gt;Portei o projeto para o Visual Studio 2008. E fiz uma an&amp;#225;lise do que j&amp;#225; foi feito e do que ainda faltava fazer.&lt;br /&gt;Acrescentei as &amp;quot;System-value semantics&amp;quot; &amp;#224; gramatica. Estas sem&amp;#226;nticas est&amp;#227;o dispon&amp;#237;veis apenas no &lt;a href="http://msdn.microsoft.com/en-us/library/bb509647(VS.85).aspx#System_Value" class="externalLink"&gt;Direct 3D 10&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;15/05/2008&lt;/h2&gt;O projeto &amp;#233; desenvolvido em C#. Como n&amp;#227;o conhecia a linguagem, aproveitei para aprender em um curso.&lt;br /&gt;&lt;br /&gt;Este curso faz parte do programa Students2Business, criado pela Microsoft e desenvolvido pelos Centros de Inova&amp;#231;&amp;#227;o e institui&amp;#231;&amp;#245;es de ensino parceiras. Resumidamente: o programa &amp;#233; gratu&amp;#237;to, o aluno pode escolher entre aulas de desenvolvimento ou de infra-estrutura de TI e &amp;#233; divido em 3 etapas. Ao final de cada etapa h&amp;#225; uma prova classificat&amp;#243;ria para a etapa seguinte. As etapas 2 e 3 possuem dura&amp;#231;&amp;#227;o de 40hs. Ao final da terceira etapa, os alunos que apresentarem os melhores projetos finais podem realizar gratuitamente provas de certifica&amp;#231;&amp;#227;o Microsoft e todos os alunos que concluirem as 3 etapas ter&amp;#227;o direito a participar do evento de formatura. Maiores informa&amp;#231;&amp;#245;es sobre o programa em &lt;a href="http://proform.msdnbrasil.tempsite.ws/public/Default.aspx" class="externalLink"&gt;http://proform.msdnbrasil.tempsite.ws/public/Default.aspx&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;30/04/2008&lt;/h2&gt;
Ol&amp;#225;!&lt;br /&gt;&lt;br /&gt;Me chamo B&amp;#225;rbara e entrei no projeto para substituir o Vitor, que se afastou para fazer doutorado. Como ele, vou utilizar este espa&amp;#231;o para periodicamente publicar os avan&amp;#231;os do projeto.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;21/03/2008&lt;/h2&gt;
Nesta semana terminei a separa&amp;#231;&amp;#227;o das fun&amp;#231;&amp;#245;es em arquivos diferentes e iniciei algumas convers&amp;#245;es de nomes de vari&amp;#225;veis de acordo com um contexto sem&amp;#226;ntico. &lt;br /&gt;&lt;br /&gt;Por exemplo, enquanto em HLSL temos: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void main(
        float4 position   : POSITION, 
        float3 normal      : NORMAL, 
	float2 uv : TEXCOORD0,
	float3 lightDir : TEXCOORD1,
	float3 eyeDir : TEXCOORD2,
	float3 spotDir : TEXCOORD3,
	float3 lightDir1 : TEXCOORD4,
	float3 spotDir1 : TEXCOORD5,
	float4 shadowUV1 : TEXCOORD6,
	float4 shadowUV2 : TEXCOORD7)
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Em GLSL teremos: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
varying vec3 tangentEyeDir;
varying vec3 tangentLightDir[2];
varying vec3 tangentSpotDir[2];
varying vec4 shadowUV[2]; 
void main() { ... }
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;uv, position e normal no HLSL seriam as vari&amp;#225;veis pr&amp;#233;-definidas gl_TexCoord[0], gl_Vertex e gl_Normal  no GLSL. &lt;br /&gt;
&lt;h2&gt;14/03/2008&lt;/h2&gt;
Nesta semana comecei a construir o separador de fun&amp;#231;&amp;#245;es. De um arquivo HLSL pode-se gerar v&amp;#225;rios GLSL. Para tal utilizo o grafo de depend&amp;#234;ncias das fun&amp;#231;&amp;#245;es declaradas no arquivo e em seus includes para separar as fun&amp;#231;&amp;#245;es corretamente, levando para o arquivo correto a formata&amp;#231;&amp;#227;o desejada e os coment&amp;#225;rios pertinentes a ela.  &lt;br /&gt;
&lt;h2&gt;07/03/2008&lt;/h2&gt;
Enquanto o HLSL permite v&amp;#225;rias entradas de execu&amp;#231;&amp;#227;o, ou seja, v&amp;#225;rias fun&amp;#231;&amp;#245;es main, o GLSL s&amp;#243; permite uma e exige o nome main. Desta forma, esta semana, trabalhei na cria&amp;#231;&amp;#227;o de um grafo de chamadas de fun&amp;#231;&amp;#245;es, para determinar quais fun&amp;#231;&amp;#245;es est&amp;#227;o sendo utilizadas para cada fun&amp;#231;&amp;#227;o de entrada no HLSL. Com esse grafo, poderei colocar cada fun&amp;#231;&amp;#227;o de entrada do HLSL em um arquivo diferente, levando tamb&amp;#233;m suas fun&amp;#231;&amp;#245;es dependentes. &lt;br /&gt;
&lt;h2&gt;29/02/2008&lt;/h2&gt;
Nesta semana trabalhei com a migra&amp;#231;&amp;#227;o da declara&amp;#231;&amp;#227;o de vari&amp;#225;veis uniform e varying, de uma fun&amp;#231;&amp;#227;o para o contexto do arquivo. &lt;br /&gt;&lt;br /&gt;Do HLSL:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
void funcao(
    // parameters 
    float4 position,
    uniform float4 lightPosition, // object space 
    uniform float4x4 texViewProj2) {..}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para o GLSL &lt;br /&gt;&lt;pre&gt;
// parameters 
uniform float4 lightPosition; // object space 
uniform float4x4 texViewProj2;

void funcao(
     float4 position
) {..}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Migra&amp;#231;&amp;#227;o simples, mas trabalhosa quando se tem uma &amp;#225;rvore de Tokens sem ignorar espa&amp;#231;os, coment&amp;#225;rios, novas linhas e tabula&amp;#231;&amp;#245;es. Acabei tento muita dificuldade em identificar os coment&amp;#225;rios relevantes que deveriam ser movidos juntamente com o par&amp;#226;metro.&lt;br /&gt;
&lt;h2&gt;22/02/2008&lt;/h2&gt;
Ol&amp;#225; a todos. &lt;br /&gt;&lt;br /&gt;Neste espa&amp;#231;o vou publicar os avan&amp;#231;os do projeto semanalmente. &lt;br /&gt;&lt;br /&gt;Nesta &amp;#250;ltima semana testei a &lt;a href="http://OGRE" class="externalLink"&gt;http://www.ogre3d.org/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; como arquitetura para os testes do projeto. Ao converter shaders de HLSL para GLSL, &amp;#233; necess&amp;#225;rio tamb&amp;#233;m converter o c&amp;#243;digo fonte do programa que os usa, da API do DirectX para a da OpenGL. Esta parte n&amp;#227;o &amp;#233; coberta por este projeto, portanto &amp;#233; manual. &lt;br /&gt;&lt;br /&gt;A OGRE &amp;#233; uma engine que permite o uso de shaders HLSL, Cg e GLSL de maneira unificada, removendo os links diretos ao DirectX ou ao OpenGL. Usando-a, n&amp;#227;o perderemos tempo migrando o c&amp;#243;digo fonte dos testes, apenas com os testes dos shaders. &lt;br /&gt;&lt;br /&gt;Tamb&amp;#233;m desenvolvi uma parte do conversor: 
&lt;ol&gt;&lt;li&gt;A troca da fun&amp;#231;&amp;#227;o &amp;quot;mul&amp;quot; pelo &amp;quot;*&amp;quot;&lt;/li&gt;
&lt;li&gt;A invers&amp;#227;o de par&amp;#226;metros na fun&amp;#231;&amp;#227;o &amp;quot;cross&amp;quot;&lt;/li&gt;
&lt;li&gt;A remo&amp;#231;&amp;#227;o de par&amp;#226;metros na fun&amp;#231;&amp;#227;o &amp;quot;main&amp;quot;&lt;/li&gt;&lt;/ol&gt;
&lt;br /&gt;E estudei algumas propriedades da representa&amp;#231;&amp;#227;o de matrizes das duas linguagens. Apesar dos elementos descritos na p&amp;#225;gina &lt;a href="http://hl2glsl.codeplex.com/wikipage?title=Differences%20Between%20HLSL%20and%20GLSL&amp;referringTitle=Blog"&gt;Differences Between HLSL and GLSL&lt;/a&gt;, ainda tenho d&amp;#250;vidas sobre o modo de trabalho com as matrizes, especialmente se devo ou n&amp;#227;o transp&amp;#244;-las.  &lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Tue, 03 Nov 2009 18:52:14 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Blog 20091103065214P</guid></item><item><title>Updated Wiki: OpenCL Tutorials</title><link>http://hl2glsl.codeplex.com/wikipage?title=OpenCL Tutorials&amp;version=2</link><description>&lt;div class="wikidoc"&gt;Ol&amp;#225;,&lt;br /&gt;estes s&amp;#227;o os tutorials dispon&amp;#237;veis at&amp;#233; agora:
&lt;ul&gt;&lt;li&gt;&lt;a href="http://hl2glsl.codeplex.com/wikipage?title=OpenCL%20Tutorials%20-%201&amp;referringTitle=OpenCL%20Tutorials"&gt;OpenCL Tutorials - 1&lt;/a&gt; (quickstart)&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;At&amp;#233;,&lt;br /&gt;&lt;br /&gt;Leonardo Chatain&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>chatain</author><pubDate>Tue, 03 Nov 2009 17:30:05 GMT</pubDate><guid isPermaLink="false">Updated Wiki: OpenCL Tutorials 20091103053005P</guid></item></channel></rss>