yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
04db5a956
master
1// render-gl.cpp 2#include "render-gl.h" 3 4#include "../immediate-renderer-base.h" 5#include "../mutable-shader-object.h" 6#include "../nvapi/nvapi-util.h" 7#include "core/slang-basic.h" 8#include "core/slang-blob.h" 9#include "core/slang-secure-crt.h" 10#include "stb_image_write.h" 11 12#if SLANG_WIN64 || SLANG_WIN64 13#define ENABLE_GL_IMPL 1 14#else 15#define ENABLE_GL_IMPL 0 16#endif 17 18#if ENABLE_GL_IMPL 19 20// TODO(tfoley): eventually we should be able to run these 21// tests on non-Windows targets to confirm that cross-compilation 22// at least *works* on those platforms... 23 24#include <windows.h> 25 26#ifdef _MSC_VER 27#include <stddef.h> 28#if (_MSC_VER < 1900 ) 29#define snprintf sprintf_s 30#endif 31#endif 32 33#pragma comment(lib, "opengl32") 34 35// clang-format off 36# include <GL/GL.h> 37# include "external/glext.h" 38# include "external/wglext.h" 39// clang-format on 40 41// We define an "X-macro" for mapping over loadable OpenGL 42// extension entry point that we will use, so that we can 43// easily write generic code to iterate over them. 44#define MAP_GL_EXTENSION_FUNCS (F ) \ 45 F(glCreateProgram, PFNGLCREATEPROGRAMPROC) \ 46 F(glCreateShader, PFNGLCREATESHADERPROC) \ 47 F(glShaderSource, PFNGLSHADERSOURCEPROC) \ 48 F(glCompileShader, PFNGLCOMPILESHADERPROC) \ 49 F(glGetShaderiv, PFNGLGETSHADERIVPROC) \ 50 F(glDeleteShader, PFNGLDELETESHADERPROC) \ 51 F(glAttachShader, PFNGLATTACHSHADERPROC) \ 52 F(glLinkProgram, PFNGLLINKPROGRAMPROC) \ 53 F(glGetProgramiv, PFNGLGETPROGRAMIVPROC) \ 54 F(glGetProgramInfoLog, PFNGLGETPROGRAMINFOLOGPROC) \ 55 F(glDeleteProgram, PFNGLDELETEPROGRAMPROC) \ 56 F(glGetShaderInfoLog, PFNGLGETSHADERINFOLOGPROC) \ 57 F(glGenBuffers, PFNGLGENBUFFERSPROC) \ 58 F(glBindBuffer, PFNGLBINDBUFFERPROC) \ 59 F(glBufferData, PFNGLBUFFERDATAPROC) \ 60 F(glCopyBufferSubData, PFNGLCOPYBUFFERSUBDATAPROC) \ 61 F(glDeleteBuffers, PFNGLDELETEBUFFERSPROC) \ 62 F(glMapBuffer, PFNGLMAPBUFFERPROC) \ 63 F(glUnmapBuffer, PFNGLUNMAPBUFFERPROC) \ 64 F(glUseProgram, PFNGLUSEPROGRAMPROC) \ 65 F(glBindBufferBase, PFNGLBINDBUFFERBASEPROC) \ 66 F(glBindBufferRange, PFNGLBINDBUFFERRANGEPROC) \ 67 F(glVertexAttribPointer, PFNGLVERTEXATTRIBPOINTERPROC) \ 68 F(glEnableVertexAttribArray, PFNGLENABLEVERTEXATTRIBARRAYPROC) \ 69 F(glDisableVertexAttribArray, PFNGLDISABLEVERTEXATTRIBARRAYPROC) \ 70 F(glDebugMessageCallback, PFNGLDEBUGMESSAGECALLBACKPROC) \ 71 F(glDispatchCompute, PFNGLDISPATCHCOMPUTEPROC) \ 72 F(glActiveTexture, PFNGLACTIVETEXTUREPROC) \ 73 F(glCreateSamplers, PFNGLCREATESAMPLERSPROC) \ 74 F(glDeleteSamplers, PFNGLDELETESAMPLERSPROC) \ 75 F(glBindSampler, PFNGLBINDSAMPLERPROC) \ 76 F(glTexImage3D, PFNGLTEXIMAGE3DPROC) \ 77 F(glBindImageTexture, PFNGLBINDIMAGETEXTUREPROC) \ 78 F(glSamplerParameteri, PFNGLSAMPLERPARAMETERIPROC) \ 79 F(glGenFramebuffers, PFNGLGENFRAMEBUFFERSPROC) \ 80 F(glDeleteFramebuffers, PFNGLDELETEFRAMEBUFFERSPROC) \ 81 F(glBindFramebuffer, PFNGLBINDFRAMEBUFFERPROC) \ 82 F(glDrawBuffers, PFNGLDRAWBUFFERSPROC) \ 83 F(glFramebufferTexture2D, PFNGLFRAMEBUFFERTEXTURE2DPROC) \ 84 F(glFramebufferTextureLayer, PFNGLFRAMEBUFFERTEXTURELAYERPROC) \ 85 F(glBlitFramebuffer, PFNGLBLITFRAMEBUFFERPROC) \ 86 F(glCheckFramebufferStatus, PFNGLCHECKFRAMEBUFFERSTATUSPROC) \ 87 F(glGenVertexArrays, PFNGLGENVERTEXARRAYSPROC) \ 88 F(glBindVertexArray, PFNGLBINDVERTEXARRAYPROC) \ 89 F(glDeleteVertexArrays, PFNGLDELETEVERTEXARRAYSPROC) \ 90 F(glDrawElementsBaseVertex, PFNGLDRAWELEMENTSBASEVERTEXPROC) \ 91/* end */ 92 93#define MAP_WGL_EXTENSION_FUNCS (F ) \ 94 F(wglCreateContextAttribsARB, PFNWGLCREATECONTEXTATTRIBSARBPROC) \ 95/* end */ 96using namespace Slang ; 97 98namespace gfx 99{ 100 101class GLDevice :public ImmediateRendererBase 102{ 103public : 104// Renderer implementation 105virtual SLANG_NO_THROW Result SLANG_MCALL initialize (const Desc & desc )override ; 106virtual void clearFrame (uint32_t mask ,bool clearDepth ,bool clearStencil )override ; 107virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain ( 108const ISwapchain ::Desc & desc , 109WindowHandle window , 110ISwapchain ** outSwapchain )override ; 111virtual SLANG_NO_THROW Result SLANG_MCALL createFramebufferLayout ( 112const IFramebufferLayout ::Desc & desc , 113IFramebufferLayout ** outLayout )override ; 114virtual SLANG_NO_THROW Result SLANG_MCALL 115createFramebuffer (const IFramebuffer ::Desc & desc ,IFramebuffer ** outFramebuffer )override ; 116virtual void setFramebuffer (IFramebuffer * frameBuffer )override ; 117virtual void setStencilReference (uint32_t referenceValue )override ; 118 119virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource ( 120const ITextureResource ::Desc & desc , 121const ITextureResource ::SubresourceData * initData , 122ITextureResource ** outResource )override ; 123virtual SLANG_NO_THROW Result SLANG_MCALL createBufferResource ( 124const IBufferResource ::Desc & desc , 125const void * initData , 126IBufferResource ** outResource )override ; 127virtual SLANG_NO_THROW Result SLANG_MCALL 128createSamplerState (ISamplerState ::Desc const & desc ,ISamplerState ** outSampler )override ; 129 130virtual SLANG_NO_THROW Result SLANG_MCALL createTextureView ( 131ITextureResource * texture , 132IResourceView ::Desc const & desc , 133IResourceView ** outView )override ; 134virtual SLANG_NO_THROW Result SLANG_MCALL createBufferView ( 135IBufferResource * buffer , 136IBufferResource * counterBuffer , 137IResourceView ::Desc const & desc , 138IResourceView ** outView )override ; 139 140virtual SLANG_NO_THROW Result SLANG_MCALL 141createInputLayout (IInputLayout ::Desc const & desc ,IInputLayout ** outLayout )override ; 142 143virtual Result createShaderObjectLayout ( 144 slang::ISession * session , 145 slang::TypeLayoutReflection * typeLayout , 146ShaderObjectLayoutBase ** outLayout )override ; 147virtual Result createShaderObject (ShaderObjectLayoutBase * layout ,IShaderObject ** outObject ) 148override ; 149virtual Result createMutableShaderObject ( 150ShaderObjectLayoutBase * layout , 151IShaderObject ** outObject )override ; 152virtual Result createRootShaderObject (IShaderProgram * program ,ShaderObjectBase ** outObject ) 153override ; 154virtual void bindRootShaderObject (IShaderObject * shaderObject )override ; 155 156virtual SLANG_NO_THROW Result SLANG_MCALL createProgram ( 157const IShaderProgram ::Desc & desc , 158IShaderProgram ** outProgram , 159ISlangBlob ** outDiagnosticBlob )override ; 160virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState ( 161const GraphicsPipelineStateDesc & desc , 162IPipelineState ** outState )override ; 163virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState ( 164const ComputePipelineStateDesc & desc , 165IPipelineState ** outState )override ; 166 167virtual void copyBuffer ( 168IBufferResource * dst , 169size_t dstOffset , 170IBufferResource * src , 171size_t srcOffset , 172size_t size )override ; 173virtual SLANG_NO_THROW Result SLANG_MCALL readTextureResource ( 174ITextureResource * texture , 175ResourceState state , 176ISlangBlob ** outBlob , 177size_t * outRowPitch , 178size_t * outPixelSize )override ; 179 180virtual void * map (IBufferResource * buffer ,MapFlavor flavor )override ; 181virtual void unmap (IBufferResource * buffer ,size_t offsetWritten ,size_t sizeWritten )override ; 182virtual void setPrimitiveTopology (PrimitiveTopology topology )override ; 183 184virtual void setVertexBuffers ( 185GfxIndex startSlot , 186GfxCount slotCount , 187IBufferResource * const * buffers , 188const Offset * offsets )override ; 189virtual void setIndexBuffer (IBufferResource * buffer ,Format indexFormat ,Offset offset ) 190override ; 191virtual void setViewports (GfxCount count ,Viewport const * viewports )override ; 192virtual void setScissorRects (GfxCount count ,ScissorRect const * rects )override ; 193virtual void setPipelineState (IPipelineState * state )override ; 194virtual void draw (GfxCount vertexCount ,GfxCount startVertex )override ; 195virtual void drawIndexed (GfxCount indexCount ,GfxIndex startIndex ,GfxIndex baseVertex ) 196override ; 197virtual void drawInstanced ( 198GfxCount vertexCount , 199GfxCount instanceCount , 200GfxIndex startVertex , 201GfxIndex startInstanceLocation )override ; 202virtual void drawIndexedInstanced ( 203GfxCount indexCount , 204GfxCount instanceCount , 205GfxIndex startIndexLocation , 206GfxIndex baseVertexLocation , 207GfxIndex startInstanceLocation )override ; 208virtual void dispatchCompute (int x ,int y ,int z )override ; 209virtual void submitGpuWork ()override {} 210virtual void waitForGpu ()override {} 211virtual void writeTimestamp (IQueryPool * pool ,GfxIndex index )override 212 { 213SLANG_UNUSED (pool ); 214SLANG_UNUSED (index ); 215 } 216virtual SLANG_NO_THROW Result SLANG_MCALL 217createQueryPool (const IQueryPool ::Desc & desc ,IQueryPool ** pool )override 218 { 219SLANG_UNUSED (desc ); 220* pool = nullptr ; 221return SLANG_E_NOT_IMPLEMENTED ; 222 } 223virtual SLANG_NO_THROW const DeviceInfo & SLANG_MCALL getDeviceInfo ()const override 224 { 225return m_info ; 226 } 227 228HGLRC createGLContext (HDC hdc ); 229GLDevice (); 230 ~GLDevice (); 231 232protected : 233enum 234 { 235kMaxVertexAttributes = 16 , 236kMaxVertexStreams = 16 , 237kMaxDescriptorSetCount = 8 , 238 }; 239struct VertexAttributeFormat 240{ 241GLint componentCount ; 242GLenum componentType ; 243GLboolean normalized ; 244}; 245 246struct VertexAttributeDesc 247{ 248VertexAttributeFormat format ; 249GLuint streamIndex ; 250GLsizei offset ; 251}; 252 253class InputLayoutImpl : public InputLayoutBase 254{ 255public : 256VertexAttributeDesc m_attributes [kMaxVertexAttributes]; 257VertexStreamDesc m_streams [kMaxVertexStreams]; 258UInt m_attributeCount = 0 ; 259UInt m_streamCount = 0 ; 260}; 261 262class BufferResourceImpl : public BufferResource 263{ 264public : 265typedef BufferResource Parent ; 266 267BufferResourceImpl ( const Desc & desc, WeakSink < GLDevice >* renderer, GLuint id, GLenum target) 268: Parent (desc) 269, m_renderer (renderer) 270, m_handle (id) 271, m_target (target) 272, m_size (desc. sizeInBytes ) 273{ 274} 275~BufferResourceImpl() 276{ 277if ( auto renderer = m_renderer -> get ()) 278{ 279renderer -> glDeleteBuffers ( 1 , & m_handle); 280} 281} 282 283RefPtr < WeakSink < GLDevice >> m_renderer ; 284GLuint m_handle ; 285GLenum m_target ; 286UInt m_size ; 287 288virtual SLANG_NO_THROW DeviceAddress SLANG_MCALL getDeviceAddress () override { return 0 ; } 289 290virtual SLANG_NO_THROW Result SLANG_MCALL 291map ( MemoryRange * rangeToRead, void ** outPointer) override 292{ 293SLANG_UNUSED (rangeToRead); 294SLANG_UNUSED (outPointer); 295return SLANG_FAIL ; 296} 297 298virtual SLANG_NO_THROW Result SLANG_MCALL unmap ( MemoryRange * writtenRange) override 299{ 300SLANG_UNUSED (writtenRange); 301return SLANG_FAIL ; 302} 303}; 304 305class TextureResourceImpl : public TextureResource 306{ 307public : 308typedef TextureResource Parent ; 309 310TextureResourceImpl ( const Desc & desc, WeakSink < GLDevice >* renderer) 311: Parent (desc), m_renderer (renderer) 312{ 313m_target = 0 ; 314m_handle = 0 ; 315} 316 317~TextureResourceImpl() 318{ 319if (m_handle) 320{ 321glDeleteTextures ( 1 , & m_handle); 322} 323} 324 325RefPtr < WeakSink < GLDevice >> m_renderer ; 326GLenum m_target ; 327GLuint m_handle ; 328}; 329 330class SamplerStateImpl : public SamplerStateBase 331{ 332public : 333GLuint m_samplerID ; 334}; 335 336class ResourceViewImpl : public ResourceViewBase 337{ 338public : 339enum class Type 340{ 341Texture, 342Buffer 343}; 344Type type ; 345}; 346 347class TextureViewImpl : public ResourceViewImpl 348{ 349public : 350RefPtr < TextureResourceImpl > m_resource ; 351GLuint m_textureID ; 352GLuint m_target ; 353enum class TextureViewType 354{ 355Texture, 356Image 357}; 358TextureViewType textureViewType ; 359GLint level ; 360GLboolean layered ; 361GLint layer ; 362GLenum access ; 363GLenum format ; 364}; 365 366class BufferViewImpl : public ResourceViewImpl 367{ 368public : 369RefPtr < BufferResourceImpl > m_resource ; 370GLuint m_bufferID ; 371}; 372 373class FramebufferLayoutImpl : public FramebufferLayoutBase 374{ 375public : 376ShortList < IFramebufferLayout :: TargetLayout > m_renderTargets ; 377bool m_hasDepthStencil = false; 378IFramebufferLayout :: TargetLayout m_depthStencil ; 379}; 380 381class FramebufferImpl : public FramebufferBase 382{ 383public : 384GLuint m_framebuffer ; 385ShortList < GLenum > m_drawBuffers ; 386RefPtr < WeakSink < GLDevice >> m_renderer ; 387ShortList < RefPtr < TextureViewImpl >> renderTargetViews ; 388RefPtr < TextureViewImpl > depthStencilView ; 389ShortList < ColorClearValue > m_colorClearValues ; 390bool m_sameClearValues = true; 391DepthStencilClearValue m_depthStencilClearValue ; 392 393FramebufferImpl ( WeakSink < GLDevice >* renderer) 394: m_renderer (renderer) 395{ 396} 397~FramebufferImpl() 398{ 399if ( auto renderer = m_renderer -> get ()) 400{ 401renderer -> glDeleteFramebuffers ( 1 , & m_framebuffer); 402} 403} 404void createGLFramebuffer () 405{ 406auto renderer = m_renderer -> get (); 407renderer -> glGenFramebuffers ( 1 , & m_framebuffer); 408renderer -> glBindFramebuffer ( GL_FRAMEBUFFER , m_framebuffer); 409m_drawBuffers. clear (); 410m_colorClearValues. clear (); 411for ( Index i = 0 ; i < renderTargetViews. getCount (); i ++ ) 412{ 413auto rtv = renderTargetViews[i]. Ptr (); 414renderer -> glFramebufferTexture2D ( 415GL_FRAMEBUFFER , 416GL_COLOR_ATTACHMENT0 + ( uint32_t )i, 417GL_TEXTURE_2D , 418rtv -> m_textureID , 4190 ); 420m_drawBuffers. add ((GLenum)( GL_COLOR_ATTACHMENT0 + i)); 421if (rtv -> m_resource -> getDesc () -> optimalClearValue ) 422{ 423m_colorClearValues. add (rtv -> m_resource -> getDesc () -> optimalClearValue -> color ); 424} 425else 426{ 427m_colorClearValues. add ( ColorClearValue ()); 428} 429} 430m_sameClearValues = true; 431for ( Index i = 1 ; i < m_colorClearValues. getCount () && m_sameClearValues; i ++ ) 432{ 433for ( int j = 0 ; j < 4 ; j ++ ) 434{ 435if (m_colorClearValues[i]. floatValues [j] != 436m_colorClearValues[ 0 ]. floatValues [j]) 437{ 438m_sameClearValues = false; 439break ; 440} 441} 442} 443if (depthStencilView) 444{ 445renderer -> glFramebufferTexture2D ( 446GL_FRAMEBUFFER , 447GL_DEPTH_ATTACHMENT , 448GL_TEXTURE_2D , 449depthStencilView -> m_textureID , 4500 ); 451if (depthStencilView -> m_resource -> getDesc () -> optimalClearValue ) 452{ 453m_depthStencilClearValue = 454depthStencilView -> m_resource -> getDesc () -> optimalClearValue -> depthStencil ; 455} 456} 457auto error = renderer -> glCheckFramebufferStatus ( GL_FRAMEBUFFER ); 458if (error != GL_FRAMEBUFFER_COMPLETE ) 459{ 460return ; 461} 462} 463}; 464 465class SwapchainImpl : public ISwapchain , public ComObject 466{ 467public : 468SLANG_COM_OBJECT_IUNKNOWN_ALL 469ISwapchain * getInterface ( const Guid & guid) 470{ 471if (guid == GfxGUID ::IID_ISlangUnknown || guid == GfxGUID ::IID_ISwapchain) 472return static_cast < ISwapchain *> (this); 473return nullptr ; 474} 475 476public : 477~SwapchainImpl() 478{ 479destroyBackBufferAndFBO (); 480wglDeleteContext (m_glrc); 481:: ReleaseDC (m_hwnd, m_hdc); 482} 483void destroyBackBufferAndFBO () 484{ 485if (m_images. getCount ()) 486{ 487wglMakeCurrent (m_rendererHDC, m_rendererRC); 488if ( auto rendererRef = m_renderer -> get ()) 489{ 490rendererRef -> glDeleteFramebuffers ( 1 , & m_framebuffer); 491} 492wglMakeCurrent (m_hdc, m_glrc); 493glDeleteTextures ( 1 , & m_backBuffer); 494for ( auto image : m_images) 495image -> m_handle = 0 ; 496m_images. clear (); 497} 498} 499void createBackBufferAndFBO () 500{ 501if (m_desc. width > 0 && m_desc. height > 0 ) 502{ 503wglMakeCurrent (m_rendererHDC, m_rendererRC); 504 505glGenTextures ( 1 , & m_backBuffer); 506glBindTexture ( GL_TEXTURE_2D , m_backBuffer); 507glTexImage2D ( 508GL_TEXTURE_2D , 5090 , 510GL_RGBA8 , 511m_desc. width , 512m_desc. height , 5130 , 514GL_RGBA , 515GL_UNSIGNED_BYTE , 516nullptr ); 517 518wglMakeCurrent (m_hdc, m_glrc); 519m_renderer -> get () -> glGenFramebuffers ( 1 , & m_framebuffer); 520m_renderer -> get () -> glBindFramebuffer ( GL_READ_FRAMEBUFFER , m_framebuffer); 521m_renderer -> get () -> glFramebufferTexture2D ( 522GL_READ_FRAMEBUFFER , 523GL_COLOR_ATTACHMENT0 , 524GL_TEXTURE_2D , 525m_backBuffer, 5260 ); 527 528m_images. clear (); 529for ( GfxIndex i = 0 ; i < m_desc. imageCount ; i ++ ) 530{ 531ITextureResource :: Desc imageDesc = {}; 532imageDesc. allowedStates = ResourceStateSet ( 533ResourceState ::Present, 534ResourceState ::RenderTarget, 535ResourceState ::CopyDestination); 536imageDesc. type = IResource :: Type ::Texture2D; 537imageDesc. arraySize = 0 ; 538imageDesc. format = m_desc. format ; 539imageDesc. size . width = m_desc. width ; 540imageDesc. size . height = m_desc. height ; 541imageDesc. size . depth = 1 ; 542imageDesc. numMipLevels = 1 ; 543imageDesc. defaultState = ResourceState ::Present; 544RefPtr < TextureResourceImpl > tex = 545new TextureResourceImpl (imageDesc, m_renderer); 546tex -> m_handle = m_backBuffer; 547m_images. add (tex); 548} 549wglMakeCurrent (m_rendererHDC, m_rendererRC); 550} 551} 552Result init ( GLDevice * renderer, const ISwapchain :: Desc & desc, WindowHandle window) 553{ 554m_renderer = renderer -> m_weakRenderer . Ptr (); 555m_rendererHDC = renderer -> m_hdc ; 556m_rendererRC = renderer -> m_glContext ; 557 558m_hwnd = ( HWND )window. handleValues [ 0 ]; 559m_hdc = :: GetDC (m_hwnd); 560m_glrc = renderer -> createGLContext (m_hdc); 561m_desc = desc; 562 563createBackBufferAndFBO (); 564return SLANG_OK ; 565} 566virtual SLANG_NO_THROW const Desc & SLANG_MCALL getDesc () override { return m_desc; } 567virtual SLANG_NO_THROW Result SLANG_MCALL 568getImage ( GfxIndex index, ITextureResource ** outResource) override 569{ 570returnComPtr (outResource, m_images[index]); 571return SLANG_OK ; 572} 573virtual SLANG_NO_THROW Result SLANG_MCALL present () override 574{ 575glFlush (); 576wglMakeCurrent (m_hdc, m_glrc); 577auto renderer = m_renderer -> get (); 578renderer -> glBindFramebuffer ( GL_DRAW_FRAMEBUFFER , 0 ); 579renderer -> glBindFramebuffer ( GL_READ_FRAMEBUFFER , m_framebuffer); 580renderer -> glBlitFramebuffer ( 5810 , 5820 , 583m_desc. width , 584m_desc. height , 5850 , 5860 , 587m_desc. width , 588m_desc. height , 589GL_COLOR_BUFFER_BIT , 590GL_NEAREST ); 591SwapBuffers (m_hdc); 592wglMakeCurrent (renderer -> m_hdc , renderer -> m_glContext ); 593return SLANG_OK ; 594} 595 596virtual SLANG_NO_THROW int SLANG_MCALL acquireNextImage () override 597{ 598if (m_desc. width > 0 && m_desc. height > 0 ) 599return 0 ; 600return -1 ; 601} 602 603virtual SLANG_NO_THROW Result SLANG_MCALL resize ( GfxCount width, GfxCount height) override 604{ 605if (width > 0 && height > 0 && (width != m_desc. width || height != m_desc. height )) 606{ 607m_desc. width = width; 608m_desc. height = height; 609destroyBackBufferAndFBO (); 610createBackBufferAndFBO (); 611} 612return SLANG_OK ; 613} 614 615virtual SLANG_NO_THROW bool SLANG_MCALL isOccluded () override { return false; } 616virtual SLANG_NO_THROW Result SLANG_MCALL setFullScreenMode ( bool mode) override 617{ 618return SLANG_FAIL ; 619} 620 621public : 622RefPtr < WeakSink < GLDevice >> m_renderer = nullptr ; 623GLuint m_framebuffer ; 624GLuint m_backBuffer ; 625HGLRC m_glrc ; 626HWND m_hwnd ; 627HDC m_hdc ; 628 629HDC m_rendererHDC ; 630HGLRC m_rendererRC ; 631ISwapchain :: Desc m_desc ; 632ShortList < RefPtr < TextureResourceImpl >> m_images ; 633}; 634 635class ShaderProgramImpl : public ShaderProgramBase 636{ 637public : 638ShaderProgramImpl ( WeakSink < GLDevice >* renderer, GLuint id) 639: m_renderer (renderer), m_id (id) 640{ 641} 642~ShaderProgramImpl() 643{ 644if ( auto renderer = m_renderer -> get ()) 645{ 646renderer -> glDeleteProgram (m_id); 647} 648} 649 650GLuint m_id ; 651RefPtr < WeakSink < GLDevice >> m_renderer ; 652}; 653 654class PipelineStateImpl : public PipelineStateBase 655{ 656public : 657RefPtr < InputLayoutImpl > m_inputLayout ; 658void init ( const GraphicsPipelineStateDesc & inDesc) 659{ 660PipelineStateDesc pipelineDesc; 661pipelineDesc. type = PipelineType ::Graphics; 662pipelineDesc. graphics = inDesc; 663initializeBase (pipelineDesc); 664} 665void init ( const ComputePipelineStateDesc & inDesc) 666{ 667PipelineStateDesc pipelineDesc; 668pipelineDesc. type = PipelineType ::Compute; 669pipelineDesc. compute = inDesc; 670initializeBase (pipelineDesc); 671} 672}; 673 674struct RootBindingState 675{ 676List < RefPtr < TextureViewImpl >> textureBindings ; 677List < RefPtr < TextureViewImpl >> imageBindings ; 678List < GLuint > samplerBindings ; 679List < GLuint > uniformBufferBindings ; 680List < GLuint > storageBufferBindings ; 681}; 682 683class ShaderObjectLayoutImpl : public ShaderObjectLayoutBase 684{ 685public : 686struct BindingRangeInfo 687{ 688slang:: BindingType bindingType ; 689Index count ; 690Index baseIndex ; 691Index subObjectIndex ; 692bool isSpecializable ; 693}; 694 695struct SubObjectRangeInfo 696{ 697RefPtr < ShaderObjectLayoutImpl > layout ; 698Index bindingRangeIndex ; 699}; 700 701struct Builder 702{ 703public : 704Builder ( RendererBase * renderer, slang:: ISession * session) 705: m_renderer (renderer), m_session (session) 706{ 707} 708 709RendererBase * m_renderer ; 710slang:: ISession * m_session ; 711slang:: TypeLayoutReflection * m_elementTypeLayout ; 712 713/// The container type of this shader object. When `m_containerType` is 714/// `StructuredBuffer` or `UnsizedArray`, this shader object represents a collection 715/// instead of a single object. 716ShaderObjectContainerType m_containerType = ShaderObjectContainerType ::None; 717 718List < BindingRangeInfo > m_bindingRanges ; 719List < SubObjectRangeInfo > m_subObjectRanges ; 720 721Index m_textureCount = 0 ; 722Index m_imageCount = 0 ; 723Index m_storageBufferCount = 0 ; 724Index m_subObjectCount = 0 ; 725 726Result setElementTypeLayout (slang:: TypeLayoutReflection * typeLayout) 727{ 728typeLayout = _unwrapParameterGroups (typeLayout, m_containerType); 729 730m_elementTypeLayout = typeLayout; 731 732// Compute the binding ranges that are used to store 733// the logical contents of the object in memory. 734 735SlangInt bindingRangeCount = typeLayout -> getBindingRangeCount (); 736for ( SlangInt r = 0 ; r < bindingRangeCount; ++ r) 737{ 738slang:: BindingType slangBindingType = typeLayout -> getBindingRangeType (r); 739SlangInt count = typeLayout -> getBindingRangeBindingCount (r); 740slang:: TypeLayoutReflection * slangLeafTypeLayout = 741typeLayout -> getBindingRangeLeafTypeLayout (r); 742 743BindingRangeInfo bindingRangeInfo; 744bindingRangeInfo. bindingType = slangBindingType; 745bindingRangeInfo. count = count; 746bindingRangeInfo. isSpecializable = typeLayout -> isBindingRangeSpecializable (r); 747switch (slangBindingType) 748{ 749case slang:: BindingType ::ConstantBuffer: 750case slang:: BindingType ::ParameterBlock: 751case slang:: BindingType ::ExistentialValue: 752bindingRangeInfo. baseIndex = m_subObjectCount; 753bindingRangeInfo. subObjectIndex = m_subObjectCount; 754m_subObjectCount += count; 755break ; 756case slang:: BindingType ::RawBuffer: 757case slang:: BindingType ::MutableRawBuffer: 758if (slangLeafTypeLayout -> getType () -> getElementType () != nullptr ) 759{ 760// A structured buffer occupies both a resource slot and 761// a sub-object slot. 762bindingRangeInfo. subObjectIndex = m_subObjectCount; 763m_subObjectCount += count; 764} 765bindingRangeInfo. baseIndex = m_storageBufferCount; 766m_storageBufferCount += count; 767break ; 768case slang:: BindingType ::Sampler: 769break ; 770 771case slang:: BindingType ::Texture: 772case slang:: BindingType ::CombinedTextureSampler: 773bindingRangeInfo. baseIndex = m_textureCount; 774m_textureCount += count; 775break ; 776 777case slang:: BindingType ::MutableTexture: 778bindingRangeInfo. baseIndex = m_imageCount; 779m_imageCount += count; 780break ; 781 782case slang:: BindingType ::MutableTypedBuffer: 783bindingRangeInfo. baseIndex = m_storageBufferCount; 784m_storageBufferCount += count; 785break ; 786case slang:: BindingType ::VaryingInput: 787case slang:: BindingType ::VaryingOutput: 788break ; 789default : 790SLANG_ASSERT (! "unsupported binding type." ); 791break ; 792} 793m_bindingRanges. add (bindingRangeInfo); 794} 795 796SlangInt subObjectRangeCount = typeLayout -> getSubObjectRangeCount (); 797for ( SlangInt r = 0 ; r < subObjectRangeCount; ++ r) 798{ 799SlangInt bindingRangeIndex = typeLayout -> getSubObjectRangeBindingRangeIndex (r); 800auto slangBindingType = typeLayout -> getBindingRangeType (bindingRangeIndex); 801slang:: TypeLayoutReflection * slangLeafTypeLayout = 802typeLayout -> getBindingRangeLeafTypeLayout (bindingRangeIndex); 803 804// A sub-object range can either represent a sub-object of a known 805// type, like a `ConstantBuffer<Foo>` or `ParameterBlock<Foo>` 806// (in which case we can pre-compute a layout to use, based on 807// the type `Foo`) *or* it can represent a sub-object of some 808// existential type (e.g., `IBar`) in which case we cannot 809// know the appropraite type/layout of sub-object to allocate. 810// 811RefPtr < ShaderObjectLayoutImpl > subObjectLayout; 812if (slangBindingType != slang:: BindingType ::ExistentialValue) 813{ 814createForElementType ( 815m_renderer, 816m_session, 817slangLeafTypeLayout -> getElementTypeLayout (), 818subObjectLayout. writeRef ()); 819} 820 821SubObjectRangeInfo subObjectRange; 822subObjectRange. bindingRangeIndex = bindingRangeIndex; 823subObjectRange. layout = subObjectLayout; 824 825m_subObjectRanges. add (subObjectRange); 826} 827return SLANG_OK ; 828} 829 830SlangResult build ( ShaderObjectLayoutImpl ** outLayout) 831{ 832auto layout = RefPtr < ShaderObjectLayoutImpl > ( new ShaderObjectLayoutImpl ()); 833SLANG_RETURN_ON_FAIL (layout -> _init (this)); 834 835returnRefPtrMove (outLayout, layout); 836return SLANG_OK ; 837} 838}; 839 840static Result createForElementType ( 841RendererBase * renderer, 842slang:: ISession * session, 843slang:: TypeLayoutReflection * elementType, 844ShaderObjectLayoutImpl ** outLayout) 845{ 846Builder builder ( renderer , session ); 847builder. setElementTypeLayout (elementType); 848return builder. build (outLayout); 849} 850 851List < BindingRangeInfo > const & getBindingRanges () { return m_bindingRanges; } 852 853Index getBindingRangeCount () { return m_bindingRanges. getCount (); } 854 855BindingRangeInfo const & getBindingRange ( Index index) { return m_bindingRanges[index]; } 856 857Index getTextureCount () { return m_textureCount; } 858Index getImageCount () { return m_imageCount; } 859Index getStorageBufferCount () { return m_storageBufferCount; } 860Index getSubObjectCount () { return m_subObjectCount; } 861 862SubObjectRangeInfo const & getSubObjectRange ( Index index) 863{ 864return m_subObjectRanges[index]; 865} 866List < SubObjectRangeInfo > const & getSubObjectRanges () { return m_subObjectRanges; } 867 868RendererBase * getRenderer () { return m_renderer; } 869 870slang:: TypeReflection * getType () { return m_elementTypeLayout -> getType (); } 871 872protected : 873Result _init ( Builder const * builder) 874{ 875auto renderer = builder -> m_renderer ; 876 877initBase (renderer, builder -> m_session , builder -> m_elementTypeLayout ); 878 879m_bindingRanges = builder -> m_bindingRanges ; 880 881m_textureCount = builder -> m_textureCount ; 882m_imageCount = builder -> m_imageCount ; 883m_storageBufferCount = builder -> m_storageBufferCount ; 884m_subObjectCount = builder -> m_subObjectCount ; 885m_subObjectRanges = builder -> m_subObjectRanges ; 886 887m_containerType = builder -> m_containerType ; 888return SLANG_OK ; 889} 890 891List < BindingRangeInfo > m_bindingRanges ; 892Index m_textureCount = 0 ; 893Index m_imageCount = 0 ; 894Index m_storageBufferCount = 0 ; 895Index m_subObjectCount = 0 ; 896List < SubObjectRangeInfo > m_subObjectRanges ; 897}; 898 899class RootShaderObjectLayoutImpl : public ShaderObjectLayoutImpl 900{ 901typedef ShaderObjectLayoutImpl Super ; 902 903public : 904struct EntryPointInfo 905{ 906RefPtr < ShaderObjectLayoutImpl > layout ; 907}; 908 909struct Builder : Super :: Builder 910{ 911Builder ( 912RendererBase * renderer, 913slang:: IComponentType * program, 914slang:: ProgramLayout * programLayout) 915: Super :: Builder (renderer, program -> getSession ()) 916, m_program (program) 917, m_programLayout (programLayout) 918{ 919} 920 921Result build ( RootShaderObjectLayoutImpl ** outLayout) 922{ 923RefPtr < RootShaderObjectLayoutImpl > layout = new RootShaderObjectLayoutImpl (); 924SLANG_RETURN_ON_FAIL (layout -> _init (this)); 925 926returnRefPtrMove (outLayout, layout); 927return SLANG_OK ; 928} 929 930void addGlobalParams (slang:: VariableLayoutReflection * globalsLayout) 931{ 932setElementTypeLayout (globalsLayout -> getTypeLayout ()); 933} 934 935void addEntryPoint ( SlangStage stage, ShaderObjectLayoutImpl * entryPointLayout) 936{ 937EntryPointInfo info; 938info. layout = entryPointLayout; 939m_entryPoints. add (info); 940} 941 942slang:: IComponentType * m_program ; 943slang:: ProgramLayout * m_programLayout ; 944List < EntryPointInfo > m_entryPoints ; 945}; 946 947EntryPointInfo & getEntryPoint ( Index index) { return m_entryPoints[index]; } 948 949List < EntryPointInfo >& getEntryPoints () { return m_entryPoints; } 950 951static Result create ( 952RendererBase * renderer, 953slang:: IComponentType * program, 954slang:: ProgramLayout * programLayout, 955RootShaderObjectLayoutImpl ** outLayout) 956{ 957RootShaderObjectLayoutImpl :: Builder builder ( renderer , program , programLayout ); 958builder. addGlobalParams (programLayout -> getGlobalParamsVarLayout ()); 959 960SlangInt entryPointCount = programLayout -> getEntryPointCount (); 961for ( SlangInt e = 0 ; e < entryPointCount; ++ e) 962{ 963auto slangEntryPoint = programLayout -> getEntryPointByIndex (e); 964RefPtr < ShaderObjectLayoutImpl > entryPointLayout; 965SLANG_RETURN_ON_FAIL ( ShaderObjectLayoutImpl :: createForElementType ( 966renderer, 967program -> getSession (), 968slangEntryPoint -> getTypeLayout (), 969entryPointLayout. writeRef ())); 970builder. addEntryPoint (slangEntryPoint -> getStage (), entryPointLayout); 971} 972 973SLANG_RETURN_ON_FAIL (builder. build (outLayout)); 974 975return SLANG_OK ; 976} 977 978slang:: IComponentType * getSlangProgram () const { return m_program; } 979slang:: ProgramLayout * getSlangProgramLayout () const { return m_programLayout; } 980 981protected : 982Result _init ( Builder const * builder) 983{ 984auto renderer = builder -> m_renderer ; 985 986SLANG_RETURN_ON_FAIL ( Super :: _init (builder)); 987 988m_program = builder -> m_program ; 989m_programLayout = builder -> m_programLayout ; 990m_entryPoints = builder -> m_entryPoints ; 991return SLANG_OK ; 992} 993 994ComPtr < slang:: IComponentType > m_program ; 995slang:: ProgramLayout * m_programLayout = nullptr ; 996 997List < EntryPointInfo > m_entryPoints ; 998}; 999 1000class ShaderObjectImpl : public ShaderObjectBaseImpl < 1001ShaderObjectImpl , 1002ShaderObjectLayoutImpl , 1003SimpleShaderObjectData > 1004{ 1005public : 1006static Result create ( 1007IDevice * device, 1008ShaderObjectLayoutImpl * layout, 1009ShaderObjectImpl ** outShaderObject) 1010{ 1011auto object = RefPtr < ShaderObjectImpl > ( new ShaderObjectImpl ()); 1012SLANG_RETURN_ON_FAIL (object -> init (device, layout)); 1013 1014returnRefPtrMove (outShaderObject, object); 1015return SLANG_OK ; 1016} 1017 1018RendererBase * getDevice () { return m_layout -> getDevice (); } 1019 1020SLANG_NO_THROW GfxCount SLANG_MCALL getEntryPointCount () SLANG_OVERRIDE { return 0 ; } 1021 1022SLANG_NO_THROW Result SLANG_MCALL 1023getEntryPoint ( GfxIndex index, IShaderObject ** outEntryPoint) SLANG_OVERRIDE 1024{ 1025* outEntryPoint = nullptr ; 1026return SLANG_OK ; 1027} 1028 1029ShaderObjectLayoutImpl * getLayout () 1030{ 1031return static_cast < ShaderObjectLayoutImpl *> (m_layout. Ptr ()); 1032} 1033 1034virtual SLANG_NO_THROW const void * SLANG_MCALL getRawData () override 1035{ 1036return m_data. getBuffer (); 1037} 1038 1039virtual SLANG_NO_THROW size_t SLANG_MCALL getSize () override 1040{ 1041return ( size_t )m_data. getCount (); 1042} 1043 1044SLANG_NO_THROW Result SLANG_MCALL 1045setData ( ShaderOffset const & inOffset, void const * data, size_t inSize) SLANG_OVERRIDE 1046{ 1047Index offset = inOffset. uniformOffset ; 1048Index size = inSize; 1049 1050char * dest = m_data. getBuffer (); 1051Index availableSize = m_data. getCount (); 1052 1053// TODO: We really should bounds-check access rather than silently ignoring sets 1054// that are too large, but we have several test cases that set more data than 1055// an object actually stores on several targets... 1056// 1057if (offset < 0 ) 1058{ 1059size += offset; 1060offset = 0 ; 1061} 1062if ((offset + size) >= availableSize) 1063{ 1064size = availableSize - offset; 1065} 1066 1067memcpy (dest + offset, data, size); 1068 1069return SLANG_OK ; 1070} 1071 1072 1073SLANG_NO_THROW Result SLANG_MCALL 1074setResource ( ShaderOffset const & offset, IResourceView * resourceView) SLANG_OVERRIDE 1075{ 1076if (offset. bindingRangeIndex < 0 ) 1077return SLANG_E_INVALID_ARG ; 1078auto layout = getLayout (); 1079if (offset. bindingRangeIndex >= layout -> getBindingRangeCount ()) 1080return SLANG_E_INVALID_ARG ; 1081auto & bindingRange = layout -> getBindingRange (offset. bindingRangeIndex ); 1082 1083auto resourceViewImpl = static_cast < ResourceViewImpl *> (resourceView); 1084switch (bindingRange. bindingType ) 1085{ 1086case slang:: BindingType ::MutableRawBuffer: 1087case slang:: BindingType ::MutableTypedBuffer: 1088case slang:: BindingType ::RawBuffer: 1089case slang:: BindingType ::TypedBuffer: 1090m_storageBuffers[bindingRange. baseIndex + offset. bindingArrayIndex ] = 1091static_cast < BufferViewImpl *> (resourceView); 1092break ; 1093case slang:: BindingType ::MutableTexture: 1094m_images[bindingRange. baseIndex + offset. bindingArrayIndex ] = 1095static_cast < TextureViewImpl *> (resourceView); 1096break ; 1097case slang:: BindingType ::Texture: 1098m_textures[bindingRange. baseIndex + offset. bindingArrayIndex ] = 1099static_cast < TextureViewImpl *> (resourceView); 1100m_samplers[bindingRange. baseIndex + offset. bindingArrayIndex ] = nullptr ; 1101break ; 1102} 1103return SLANG_OK ; 1104} 1105 1106SLANG_NO_THROW Result SLANG_MCALL 1107setSampler ( ShaderOffset const & offset, ISamplerState * sampler) SLANG_OVERRIDE 1108{ 1109if (offset. bindingRangeIndex < 0 ) 1110return SLANG_E_INVALID_ARG ; 1111auto layout = getLayout (); 1112if (offset. bindingRangeIndex >= layout -> getBindingRangeCount ()) 1113return SLANG_E_INVALID_ARG ; 1114auto & bindingRange = layout -> getBindingRange (offset. bindingRangeIndex ); 1115 1116m_samplers[bindingRange. baseIndex + offset. bindingArrayIndex ] = 1117static_cast < SamplerStateImpl *> (sampler); 1118return SLANG_OK ; 1119} 1120 1121SLANG_NO_THROW Result SLANG_MCALL setCombinedTextureSampler ( 1122ShaderOffset const & offset, 1123IResourceView * textureView, 1124ISamplerState * sampler) SLANG_OVERRIDE 1125{ 1126if (offset. bindingRangeIndex < 0 ) 1127return SLANG_E_INVALID_ARG ; 1128auto layout = getLayout (); 1129if (offset. bindingRangeIndex >= layout -> getBindingRangeCount ()) 1130return SLANG_E_INVALID_ARG ; 1131auto & bindingRange = layout -> getBindingRange (offset. bindingRangeIndex ); 1132m_textures[bindingRange. baseIndex + offset. bindingArrayIndex ] = 1133static_cast < TextureViewImpl *> (textureView); 1134m_samplers[bindingRange. baseIndex + offset. bindingArrayIndex ] = 1135static_cast < SamplerStateImpl *> (sampler); 1136return SLANG_OK ; 1137} 1138 1139public : 1140protected : 1141friend class ProgramVars ; 1142 1143Result init ( IDevice * device, ShaderObjectLayoutImpl * layout) 1144{ 1145m_layout = layout; 1146 1147// If the layout tells us that there is any uniform data, 1148// then we will allocate a CPU memory buffer to hold that data 1149// while it is being set from the host. 1150// 1151// Once the user is done setting the parameters/fields of this 1152// shader object, we will produce a GPU-memory version of the 1153// uniform data (which includes values from this object and 1154// any existential-type sub-objects). 1155// 1156size_t uniformSize = layout -> getElementTypeLayout () -> getSize (); 1157if (uniformSize) 1158{ 1159m_data. setCount (uniformSize); 1160memset (m_data. getBuffer (), 0 , uniformSize); 1161} 1162 1163m_samplers. setCount (layout -> getTextureCount ()); 1164m_textures. setCount (layout -> getTextureCount ()); 1165m_images. setCount (layout -> getImageCount ()); 1166m_storageBuffers. setCount (layout -> getStorageBufferCount ()); 1167 1168// If the layout specifies that we have any sub-objects, then 1169// we need to size the array to account for them. 1170// 1171Index subObjectCount = layout -> getSubObjectCount (); 1172m_objects. setCount (subObjectCount); 1173 1174for ( auto subObjectRangeInfo : layout -> getSubObjectRanges ()) 1175{ 1176auto subObjectLayout = subObjectRangeInfo. layout ; 1177 1178// In the case where the sub-object range represents an 1179// existential-type leaf field (e.g., an `IBar`), we 1180// cannot pre-allocate the object(s) to go into that 1181// range, since we can't possibly know what to allocate 1182// at this point. 1183// 1184if (!subObjectLayout) 1185continue ; 1186// 1187// Otherwise, we will allocate a sub-object to fill 1188// in each entry in this range, based on the layout 1189// information we already have. 1190 1191auto & bindingRangeInfo = 1192layout -> getBindingRange (subObjectRangeInfo. bindingRangeIndex ); 1193for ( Index i = 0 ; i < bindingRangeInfo. count ; ++ i) 1194{ 1195RefPtr < ShaderObjectImpl > subObject; 1196SLANG_RETURN_ON_FAIL ( 1197ShaderObjectImpl :: create (device, subObjectLayout, subObject. writeRef ())); 1198m_objects[bindingRangeInfo. subObjectIndex + i] = subObject; 1199} 1200} 1201 1202return SLANG_OK ; 1203} 1204 1205/// Write the uniform/ordinary data of this object into the given `dest` buffer at the given 1206/// `offset` 1207Result _writeOrdinaryData ( 1208GLDevice * device, 1209BufferResourceImpl * buffer, 1210size_t offset, 1211size_t destSize, 1212ShaderObjectLayoutImpl * specializedLayout) 1213{ 1214auto src = m_data. getBuffer (); 1215auto srcSize = size_t (m_data. getCount ()); 1216 1217SLANG_ASSERT (srcSize <= destSize); 1218 1219device -> uploadBufferData (buffer, offset, srcSize, src); 1220 1221// In the case where this object has any sub-objects of 1222// existential/interface type, we need to recurse on those objects 1223// that need to write their state into an appropriate "pending" allocation. 1224// 1225// Note: Any values that could fit into the "payload" included 1226// in the existential-type field itself will have already been 1227// written as part of `setObject()`. This loop only needs to handle 1228// those sub-objects that do not "fit." 1229// 1230// An implementers looking at this code might wonder if things could be changed 1231// so that *all* writes related to sub-objects for interface-type fields could 1232// be handled in this one location, rather than having some in `setObject()` and 1233// others handled here. 1234// 1235Index subObjectRangeCounter = 0 ; 1236for ( auto const & subObjectRangeInfo : specializedLayout -> getSubObjectRanges ()) 1237{ 1238Index subObjectRangeIndex = subObjectRangeCounter ++ ; 1239auto const & bindingRangeInfo = 1240specializedLayout -> getBindingRange (subObjectRangeInfo. bindingRangeIndex ); 1241 1242// We only need to handle sub-object ranges for interface/existential-type fields, 1243// because fields of constant-buffer or parameter-block type are responsible for 1244// the ordinary/uniform data of their own existential/interface-type sub-objects. 1245// 1246if (bindingRangeInfo. bindingType != slang:: BindingType ::ExistentialValue) 1247continue ; 1248 1249// Each sub-object range represents a single "leaf" field, but might be nested 1250// under zero or more outer arrays, such that the number of existential values 1251// in the same range can be one or more. 1252// 1253auto count = bindingRangeInfo. count ; 1254 1255// We are not concerned with the case where the existential value(s) in the range 1256// git into the payload part of the leaf field. 1257// 1258// In the case where the value didn't fit, the Slang layout strategy would have 1259// considered the requirements of the value as a "pending" allocation, and would 1260// allocate storage for the ordinary/uniform part of that pending allocation inside 1261// of the parent object's type layout. 1262// 1263// Here we assume that the Slang reflection API can provide us with a single byte 1264// offset and stride for the location of the pending data allocation in the 1265// specialized type layout, which will store the values for this sub-object range. 1266// 1267// TODO: The reflection API functions we are assuming here haven't been implemented 1268// yet, so the functions being called here are stubs. 1269// 1270// TODO: It might not be that a single sub-object range can reliably map to a single 1271// contiguous array with a single stride; we need to carefully consider what the 1272// layout logic does for complex cases with multiple layers of nested arrays and 1273// structures. 1274// 1275size_t subObjectRangePendingDataOffset = 12760 ; // subObjectRangeInfo.offset.pendingOrdinaryData; 1277size_t subObjectRangePendingDataStride = 12780 ; // subObjectRangeInfo.stride.pendingOrdinaryData; 1279 1280// If the range doesn't actually need/use the "pending" allocation at all, then 1281// we need to detect that case and skip such ranges. 1282// 1283// TODO: This should probably be handled on a per-object basis by caching a "does it 1284// fit?" bit as part of the information for bound sub-objects, given that we already 1285// compute the "does it fit?" status as part of `setObject()`. 1286// 1287if (subObjectRangePendingDataOffset == 0 ) 1288continue ; 1289 1290for ( Slang :: Index i = 0 ; i < count; ++ i) 1291{ 1292auto subObject = m_objects[bindingRangeInfo. subObjectIndex + i]; 1293 1294RefPtr < ShaderObjectLayoutImpl > subObjectLayout; 1295SLANG_RETURN_ON_FAIL ( 1296subObject -> _getSpecializedLayout (subObjectLayout. writeRef ())); 1297 1298auto subObjectOffset = 1299subObjectRangePendingDataOffset + i * subObjectRangePendingDataStride; 1300 1301subObject -> _writeOrdinaryData ( 1302device, 1303buffer, 1304offset + subObjectOffset, 1305destSize - subObjectOffset, 1306subObjectLayout); 1307} 1308} 1309 1310return SLANG_OK ; 1311} 1312 1313/// Ensure that the `m_ordinaryDataBuffer` has been created, if it is needed 1314Result _ensureOrdinaryDataBufferCreatedIfNeeded ( GLDevice * device) 1315{ 1316// If we have already created a buffer to hold ordinary data, then we should 1317// simply re-use that buffer rather than re-create it. 1318// 1319// TODO: Simply re-using the buffer without any kind of validation checks 1320// means that we are assuming that users cannot or will not perform any `set` 1321// operations on a shader object once an operation has requested this buffer 1322// be created. We need to enforce that rule if we want to rely on it. 1323// 1324if (m_ordinaryDataBuffer) 1325return SLANG_OK ; 1326 1327// Computing the size of the ordinary data buffer is *not* just as simple 1328// as using the size of the `m_ordinayData` array that we store. The reason 1329// for the added complexity is that interface-type fields may lead to the 1330// storage being specialized such that it needs extra appended data to 1331// store the concrete values that logically belong in those interface-type 1332// fields but wouldn't fit in the fixed-size allocation we gave them. 1333// 1334// TODO: We need to actually implement that logic by using reflection 1335// data computed for the specialized type of this shader object. 1336// For now we just make the simple assumption described above despite 1337// knowing that it is false. 1338// 1339RefPtr < ShaderObjectLayoutImpl > specializedLayout; 1340SLANG_RETURN_ON_FAIL ( _getSpecializedLayout (specializedLayout. writeRef ())); 1341 1342auto specializedOrdinaryDataSize = specializedLayout -> getElementTypeLayout () -> getSize (); 1343if (specializedOrdinaryDataSize == 0 ) 1344return SLANG_OK ; 1345 1346// Once we have computed how large the buffer should be, we can allocate 1347// it using the existing public `IDevice` API. 1348// 1349 1350ComPtr < IBufferResource > bufferResourcePtr; 1351IBufferResource :: Desc bufferDesc; 1352bufferDesc. type = IResource :: Type ::Buffer; 1353bufferDesc. sizeInBytes = specializedOrdinaryDataSize; 1354bufferDesc. defaultState = ResourceState ::ConstantBuffer; 1355bufferDesc. allowedStates = 1356ResourceStateSet ( ResourceState ::ConstantBuffer, ResourceState ::CopyDestination); 1357bufferDesc. memoryType = MemoryType ::Upload; 1358SLANG_RETURN_ON_FAIL ( 1359device -> createBufferResource (bufferDesc, nullptr , bufferResourcePtr. writeRef ())); 1360m_ordinaryDataBuffer = static_cast < BufferResourceImpl *> (bufferResourcePtr. get ()); 1361 1362// Once the buffer is allocated, we can use `_writeOrdinaryData` to fill it in. 1363// 1364// Note that `_writeOrdinaryData` is potentially recursive in the case 1365// where this object contains interface/existential-type fields, so we 1366// don't need or want to inline it into this call site. 1367// 1368SLANG_RETURN_ON_FAIL ( _writeOrdinaryData ( 1369device, 1370m_ordinaryDataBuffer, 13710 , 1372specializedOrdinaryDataSize, 1373specializedLayout)); 1374 1375return SLANG_OK ; 1376} 1377 1378/// Bind the buffer for ordinary/uniform data, if needed 1379Result _bindOrdinaryDataBufferIfNeeded ( GLDevice * device, RootBindingState * bindingState) 1380{ 1381// We start by ensuring that the buffer is created, if it is needed. 1382// 1383SLANG_RETURN_ON_FAIL ( _ensureOrdinaryDataBufferCreatedIfNeeded (device)); 1384 1385// If we did indeed need/create a buffer, then we must bind it 1386// into root binding state. 1387// 1388if (m_ordinaryDataBuffer) 1389{ 1390bindingState -> uniformBufferBindings . add (m_ordinaryDataBuffer -> m_handle ); 1391} 1392 1393return SLANG_OK ; 1394} 1395 1396public : 1397virtual Result bindObject ( GLDevice * device, RootBindingState * bindingState) 1398{ 1399ShaderObjectLayoutImpl * layout = getLayout (); 1400 1401Index baseRangeIndex = 0 ; 1402SLANG_RETURN_ON_FAIL ( _bindOrdinaryDataBufferIfNeeded (device, bindingState)); 1403 1404for ( auto sampler : m_samplers) 1405bindingState -> samplerBindings . add (sampler ? sampler -> m_samplerID : 0 ); 1406 1407bindingState -> textureBindings . addRange (m_textures); 1408bindingState -> imageBindings . addRange (m_images); 1409 1410for ( auto buffer : m_storageBuffers) 1411bindingState -> storageBufferBindings . add (buffer ? buffer -> m_bufferID : 0 ); 1412 1413for ( auto const & subObjectRange : layout -> getSubObjectRanges ()) 1414{ 1415auto subObjectLayout = subObjectRange. layout ; 1416auto const & bindingRange = 1417layout -> getBindingRange (subObjectRange. bindingRangeIndex ); 1418 1419switch (bindingRange. bindingType ) 1420{ 1421case slang:: BindingType ::ConstantBuffer: 1422case slang:: BindingType ::ParameterBlock: 1423case slang:: BindingType ::ExistentialValue: 1424break ; 1425default : 1426continue ; 1427} 1428 1429for ( Index i = 0 ; i < bindingRange. count ; i ++ ) 1430{ 1431m_objects[i + bindingRange. subObjectIndex ] -> bindObject (device, bindingState); 1432} 1433} 1434 1435return SLANG_OK ; 1436} 1437 1438List < RefPtr < TextureViewImpl >> m_textures ; 1439 1440List < RefPtr < TextureViewImpl >> m_images ; 1441 1442List < RefPtr < SamplerStateImpl >> m_samplers ; 1443 1444List < RefPtr < BufferViewImpl >> m_storageBuffers ; 1445 1446/// A constant buffer used to stored ordinary data for this object 1447/// and existential-type sub-objects. 1448/// 1449/// Created on demand with `_createOrdinaryDataBufferIfNeeded()` 1450RefPtr < BufferResourceImpl > m_ordinaryDataBuffer ; 1451 1452/// Get the layout of this shader object with specialization arguments considered 1453/// 1454/// This operation should only be called after the shader object has been 1455/// fully filled in and finalized. 1456/// 1457Result _getSpecializedLayout ( ShaderObjectLayoutImpl ** outLayout) 1458{ 1459if (!m_specializedLayout) 1460{ 1461SLANG_RETURN_ON_FAIL ( _createSpecializedLayout (m_specializedLayout. writeRef ())); 1462} 1463returnRefPtr (outLayout, m_specializedLayout); 1464return SLANG_OK ; 1465} 1466 1467/// Create the layout for this shader object with specialization arguments considered 1468/// 1469/// This operation is virtual so that it can be customized by `ProgramVars`. 1470/// 1471virtual Result _createSpecializedLayout ( ShaderObjectLayoutImpl ** outLayout) 1472{ 1473ExtendedShaderObjectType extendedType; 1474SLANG_RETURN_ON_FAIL ( getSpecializedShaderObjectType ( & extendedType)); 1475 1476auto renderer = getRenderer (); 1477RefPtr < ShaderObjectLayoutImpl > layout; 1478SLANG_RETURN_ON_FAIL (renderer -> getShaderObjectLayout ( 1479m_layout -> m_slangSession , 1480extendedType. slangType , 1481m_layout -> getContainerType (), 1482( ShaderObjectLayoutBase ** )layout. writeRef ())); 1483 1484returnRefPtrMove (outLayout, layout); 1485return SLANG_OK ; 1486} 1487 1488RefPtr < ShaderObjectLayoutImpl > m_specializedLayout ; 1489}; 1490 1491class MutableShaderObjectImpl 1492: public MutableShaderObject < MutableShaderObjectImpl , ShaderObjectLayoutImpl > 1493{ 1494}; 1495 1496class RootShaderObjectImpl : public ShaderObjectImpl 1497{ 1498typedef ShaderObjectImpl Super ; 1499 1500public : 1501virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef () override { return 1 ; } 1502virtual SLANG_NO_THROW uint32_t SLANG_MCALL release () override { return 1 ; } 1503 1504public : 1505static Result create ( 1506IDevice * device, 1507RootShaderObjectLayoutImpl * layout, 1508RootShaderObjectImpl ** outShaderObject) 1509{ 1510RefPtr < RootShaderObjectImpl > object = new RootShaderObjectImpl (); 1511SLANG_RETURN_ON_FAIL (object -> init (device, layout)); 1512 1513returnRefPtrMove (outShaderObject, object); 1514return SLANG_OK ; 1515} 1516 1517RootShaderObjectLayoutImpl * getLayout () 1518{ 1519return static_cast < RootShaderObjectLayoutImpl *> (m_layout. Ptr ()); 1520} 1521 1522SLANG_NO_THROW GfxCount SLANG_MCALL getEntryPointCount () SLANG_OVERRIDE 1523{ 1524return ( GfxCount )m_entryPoints. getCount (); 1525} 1526SLANG_NO_THROW SlangResult SLANG_MCALL 1527getEntryPoint ( GfxIndex index, IShaderObject ** outEntryPoint) SLANG_OVERRIDE 1528{ 1529* outEntryPoint = m_entryPoints[index]; 1530m_entryPoints[index] -> addRef (); 1531return SLANG_OK ; 1532} 1533 1534virtual Result collectSpecializationArgs ( ExtendedShaderObjectTypeList & args) override 1535{ 1536SLANG_RETURN_ON_FAIL ( ShaderObjectImpl :: collectSpecializationArgs (args)); 1537for ( auto & entryPoint : m_entryPoints) 1538{ 1539SLANG_RETURN_ON_FAIL (entryPoint -> collectSpecializationArgs (args)); 1540} 1541return SLANG_OK ; 1542} 1543 1544protected : 1545virtual Result bindObject ( GLDevice * device, RootBindingState * bindingState) override 1546{ 1547SLANG_RETURN_ON_FAIL ( Super :: bindObject (device, bindingState)); 1548 1549auto entryPointCount = m_entryPoints. getCount (); 1550for ( Index i = 0 ; i < entryPointCount; ++ i) 1551{ 1552auto entryPoint = m_entryPoints[i]; 1553SLANG_RETURN_ON_FAIL (entryPoint -> bindObject (device, bindingState)); 1554} 1555 1556return SLANG_OK ; 1557} 1558 1559Result init ( IDevice * device, RootShaderObjectLayoutImpl * layout) 1560{ 1561SLANG_RETURN_ON_FAIL ( Super :: init (device, layout)); 1562 1563for ( auto entryPointInfo : layout -> getEntryPoints ()) 1564{ 1565RefPtr < ShaderObjectImpl > entryPoint; 1566SLANG_RETURN_ON_FAIL ( 1567ShaderObjectImpl :: create (device, entryPointInfo. layout , entryPoint. writeRef ())); 1568m_entryPoints. add (entryPoint); 1569} 1570 1571return SLANG_OK ; 1572} 1573 1574Result _createSpecializedLayout ( ShaderObjectLayoutImpl ** outLayout) SLANG_OVERRIDE 1575{ 1576ExtendedShaderObjectTypeList specializationArgs; 1577SLANG_RETURN_ON_FAIL ( collectSpecializationArgs (specializationArgs)); 1578 1579// Note: There is an important policy decision being made here that we need 1580// to approach carefully. 1581// 1582// We are doing two different things that affect the layout of a program: 1583// 1584// 1. We are *composing* one or more pieces of code (notably the shared global/module 1585// stuff and the per-entry-point stuff). 1586// 1587// 2. We are *specializing* code that includes generic/existential parameters 1588// to concrete types/values. 1589// 1590// We need to decide the relative *order* of these two steps, because of how it impacts 1591// layout. The layout for `specialize(compose(A,B), X, Y)` is potentially different 1592// form that of `compose(specialize(A,X), speciealize(B,Y))`, even when both are 1593// semantically equivalent programs. 1594// 1595// Right now we are using the first option: we are first generating a full composition 1596// of all the code we plan to use (global scope plus all entry points), and then 1597// specializing it to the concatenated specialization argumenst for all of that. 1598// 1599// In some cases, though, this model isn't appropriate. For example, when dealing with 1600// ray-tracing shaders and local root signatures, we really want the parameters of each 1601// entry point (actually, each entry-point *group*) to be allocated distinct storage, 1602// which really means we want to compute something like: 1603// 1604// SpecializedGlobals = specialize(compose(ModuleA, ModuleB, ...), X, Y, ...) 1605// 1606// SpecializedEP1 = compose(SpecializedGlobals, specialize(EntryPoint1, T, U, ...)) 1607// SpecializedEP2 = compose(SpecializedGlobals, specialize(EntryPoint2, A, B, ...)) 1608// 1609// Note how in this case all entry points agree on the layout for the shared/common 1610// parmaeters, but their layouts are also independent of one another. 1611// 1612// Furthermore, in this example, loading another entry point into the system would not 1613// rquire re-computing the layouts (or generated kernel code) for any of the entry 1614// points that had already been loaded (in contrast to a compose-then-specialize 1615// approach). 1616// 1617ComPtr < slang:: IComponentType > specializedComponentType; 1618ComPtr < slang:: IBlob > diagnosticBlob; 1619auto result = getLayout () -> getSlangProgram () -> specialize ( 1620specializationArgs. components . getArrayView (). getBuffer (), 1621specializationArgs. getCount (), 1622specializedComponentType. writeRef (), 1623diagnosticBlob. writeRef ()); 1624 1625// TODO: print diagnostic message via debug output interface. 1626 1627if (result != SLANG_OK ) 1628return result; 1629 1630auto slangSpecializedLayout = specializedComponentType -> getLayout (); 1631RefPtr < RootShaderObjectLayoutImpl > specializedLayout; 1632RootShaderObjectLayoutImpl :: create ( 1633getRenderer (), 1634specializedComponentType, 1635slangSpecializedLayout, 1636specializedLayout. writeRef ()); 1637 1638// Note: Computing the layout for the specialized program will have also computed 1639// the layouts for the entry points, and we really need to attach that information 1640// to them so that they don't go and try to compute their own specializations. 1641// 1642// TODO: Well, if we move to the specialization model described above then maybe 1643// we *will* want entry points to do their own specialization work... 1644// 1645auto entryPointCount = m_entryPoints. getCount (); 1646for ( Index i = 0 ; i < entryPointCount; ++ i) 1647{ 1648auto entryPointInfo = specializedLayout -> getEntryPoint (i); 1649auto entryPointVars = m_entryPoints[i]; 1650 1651entryPointVars -> m_specializedLayout = entryPointInfo. layout ; 1652} 1653 1654returnRefPtrMove (outLayout, specializedLayout); 1655return SLANG_OK ; 1656} 1657 1658 1659List < RefPtr < ShaderObjectImpl >> m_entryPoints ; 1660}; 1661 1662enum class GlPixelFormat 1663{ 1664Unknown, 1665R8G8B8A8_UNORM , 1666D32_FLOAT , 1667D_Unorm24_S8, 1668D32_FLOAT_S8 , 1669CountOf, 1670}; 1671 1672struct GlPixelFormatInfo 1673{ 1674GLint internalFormat ; // such as GL_RGBA8 1675GLenum format ; // such as GL_RGBA 1676GLenum formatType ; // such as GL_UNSIGNED_BYTE 1677}; 1678 1679// void destroyBindingEntries(const BindingState::Desc& desc, const BindingDetail* details); 1680 1681void bindBufferImpl ( 1682int target, 1683UInt startSlot, 1684UInt slotCount, 1685BufferResource * const * buffers, 1686const UInt * offsets); 1687void flushStateForDraw (); 1688GLuint loadShader ( GLenum stage, char const * source); 1689void debugCallback ( 1690GLenum source, 1691GLenum type, 1692GLuint id, 1693GLenum severity, 1694GLsizei length, 1695const GLchar * message); 1696 1697/// Returns GlPixelFormat::Unknown if not an equivalent 1698static GlPixelFormat _getGlPixelFormat ( Format format); 1699 1700static void APIENTRY staticDebugCallback ( 1701GLenum source, 1702GLenum type, 1703GLuint id, 1704GLenum severity, 1705GLsizei length, 1706const GLchar * message, 1707const void * userParam); 1708static VertexAttributeFormat getVertexAttributeFormat ( Format format); 1709 1710static void compileTimeAsserts (); 1711 1712// GLDevice members. 1713 1714DeviceInfo m_info; 1715String m_adapterName; 1716 1717HDC m_hdc; 1718HGLRC m_glContext = 0 ; 1719uint32_t m_stencilRef = 0 ; 1720 1721GLuint m_vao; 1722RefPtr < PipelineStateImpl > m_currentPipelineState; 1723RefPtr < FramebufferImpl > m_currentFramebuffer; 1724RefPtr < WeakSink < GLDevice >> m_weakRenderer; 1725 1726RootBindingState m_rootBindingState; 1727 1728GLenum m_boundPrimitiveTopology = GL_TRIANGLES ; 1729GLuint m_boundVertexStreamBuffers[kMaxVertexStreams]; 1730UInt m_boundVertexStreamOffsets[kMaxVertexStreams]; 1731GLuint m_boundIndexBuffer = 0 ; 1732UInt m_boundIndexBufferOffset = 0 ; 1733UInt m_boundIndexBufferSize = 0 ; 1734 1735Desc m_desc; 1736WindowHandle m_windowHandle; 1737// Declare a function pointer for each OpenGL 1738// extension function we need to load 1739#define DECLARE_GL_EXTENSION_FUNC ( NAME , TYPE ) TYPE NAME; 1740MAP_GL_EXTENSION_FUNCS ( DECLARE_GL_EXTENSION_FUNC ) 1741MAP_WGL_EXTENSION_FUNCS ( DECLARE_GL_EXTENSION_FUNC ) 1742#undef DECLARE_GL_EXTENSION_FUNC 1743 1744static const GlPixelFormatInfo s_pixelFormatInfos[]; /// Maps GlPixelFormat to a format info 1745}; 1746 1747/* static */ GLDevice :: GlPixelFormat GLDevice :: _getGlPixelFormat ( Format format) 1748{ 1749switch (format) 1750{ 1751case Format :: R8G8B8A8_UNORM : 1752return GlPixelFormat :: R8G8B8A8_UNORM ; 1753case Format :: D32_FLOAT : 1754return GlPixelFormat :: D32_FLOAT ; 1755// case Format::D24_UNORM_S8_UINT: return GlPixelFormat::D_Unorm24_S8; 1756case Format :: D32_FLOAT_S8_UINT : 1757return GlPixelFormat :: D32_FLOAT_S8 ; 1758 1759default : 1760return GlPixelFormat ::Unknown; 1761} 1762} 1763 1764/* static */ const GLDevice :: GlPixelFormatInfo GLDevice ::s_pixelFormatInfos[] = { 1765// internalType, format, formatType 1766{ 0 , 0 , 0 }, // GlPixelFormat::Unknown 1767{ GL_RGBA8 , GL_RGBA , GL_UNSIGNED_BYTE }, // GlPixelFormat::R8G8B8A8_UNORM 1768{ GL_DEPTH_COMPONENT32F , GL_DEPTH_COMPONENT , GL_UNSIGNED_BYTE }, // GlPixelFormat::D32_FLOAT 1769{ GL_DEPTH24_STENCIL8 , GL_DEPTH_STENCIL , GL_UNSIGNED_BYTE }, // GlPixelFormat::D_Unorm24_S8 1770{ GL_DEPTH32F_STENCIL8 , 1771GL_DEPTH_STENCIL , 1772GL_FLOAT_32_UNSIGNED_INT_24_8_REV }, // GlPixelFormat::D32_FLOAT_S8 1773 1774}; 1775 1776/* static */ void GLDevice :: compileTimeAsserts () 1777{ 1778SLANG_COMPILE_TIME_ASSERT ( SLANG_COUNT_OF (s_pixelFormatInfos) == int ( GlPixelFormat ::CountOf)); 1779} 1780 1781void GLDevice :: debugCallback ( 1782GLenum source, 1783GLenum type, 1784GLuint id, 1785GLenum severity, 1786GLsizei length, 1787const GLchar * message) 1788{ 1789DebugMessageType msgType = DebugMessageType ::Info; 1790switch (type) 1791{ 1792case GL_DEBUG_TYPE_ERROR : 1793msgType = DebugMessageType ::Error; 1794break ; 1795default : 1796break ; 1797} 1798getDebugCallback () -> handleMessage (msgType, DebugMessageSource ::Driver, message); 1799} 1800 1801/* static */ void APIENTRY GLDevice :: staticDebugCallback ( 1802GLenum source, 1803GLenum type, 1804GLuint id, 1805GLenum severity, 1806GLsizei length, 1807const GLchar * message, 1808const void * userParam) 1809{ 1810(( GLDevice * )userParam) -> debugCallback (source, type, id, severity, length, message); 1811} 1812 1813/* static */ GLDevice :: VertexAttributeFormat GLDevice :: getVertexAttributeFormat ( Format format) 1814{ 1815switch (format) 1816{ 1817default : 1818assert (! "unexpected" ); 1819return VertexAttributeFormat (); 1820 1821#define CASE ( NAME , COUNT , TYPE , NORMALIZED ) \ 1822case Format::NAME: \ 1823do \ 1824{ \ 1825VertexAttributeFormat result = {COUNT, TYPE, NORMALIZED}; \ 1826return result; \ 1827} while (0) 1828 1829CASE ( R32G32B32A32_FLOAT , 4 , GL_FLOAT , GL_FALSE ); 1830CASE ( R32G32B32_FLOAT , 3 , GL_FLOAT , GL_FALSE ); 1831CASE ( R32G32_FLOAT , 2 , GL_FLOAT , GL_FALSE ); 1832CASE ( R32_FLOAT , 1 , GL_FLOAT , GL_FALSE ); 1833#undef CASE 1834} 1835} 1836 1837void GLDevice :: bindBufferImpl ( 1838int target, 1839UInt startSlot, 1840UInt slotCount, 1841BufferResource * const * buffers, 1842const UInt * offsets) 1843{ 1844for ( UInt ii = 0 ; ii < slotCount; ++ ii) 1845{ 1846UInt slot = startSlot + ii; 1847 1848BufferResourceImpl * buffer = static_cast < BufferResourceImpl *> (buffers[ii]); 1849GLuint bufferID = buffer ? buffer -> m_handle : 0 ; 1850 1851assert (!offsets || !offsets[ii]); 1852 1853glBindBufferBase (target, ( GLuint )slot, bufferID); 1854} 1855} 1856 1857void GLDevice :: flushStateForDraw () 1858{ 1859if (m_currentFramebuffer) 1860{ 1861glBindFramebuffer ( GL_FRAMEBUFFER , m_currentFramebuffer -> m_framebuffer ); 1862glDrawBuffers ( 1863( GLsizei )m_currentFramebuffer -> m_drawBuffers . getCount (), 1864m_currentFramebuffer -> m_drawBuffers . getArrayView (). getBuffer ()); 1865} 1866auto inputLayout = m_currentPipelineState -> m_inputLayout . Ptr (); 1867auto attrCount = Index (inputLayout -> m_attributeCount ); 1868for ( Index ii = 0 ; ii < attrCount; ++ ii) 1869{ 1870auto & attr = inputLayout -> m_attributes [ii]; 1871 1872auto streamIndex = attr. streamIndex ; 1873 1874auto stride = inputLayout -> m_streams [streamIndex]. stride ; 1875 1876glBindBuffer ( GL_ARRAY_BUFFER , m_boundVertexStreamBuffers[streamIndex]); 1877 1878glVertexAttribPointer ( 1879( GLuint )ii, 1880attr. format . componentCount , 1881attr. format . componentType , 1882attr. format . normalized , 1883( GLsizei )stride, 1884( GLvoid * )(attr. offset + m_boundVertexStreamOffsets[streamIndex])); 1885 1886glEnableVertexAttribArray (( GLuint )ii); 1887} 1888for ( Index ii = attrCount; ii < kMaxVertexStreams; ++ ii) 1889{ 1890glDisableVertexAttribArray (( GLuint )ii); 1891} 1892if (m_boundIndexBuffer) 1893{ 1894glBindBufferRange ( 1895GL_ELEMENT_ARRAY_BUFFER , 18960 , 1897m_boundIndexBuffer, 1898m_boundIndexBufferOffset, 1899m_boundIndexBufferSize); 1900} 1901} 1902 1903GLuint GLDevice :: loadShader ( GLenum stage, const char * source) 1904{ 1905// GLSL is monumentally stupid. It officially requires the `#version` directive 1906// to be the first thing in the file, which wouldn't be so bad but the API 1907// doesn't provide a way to pass a `#define` into your shader other than by 1908// prepending it to the whole thing. 1909// 1910// We are going to solve this problem by doing some surgery on the source 1911// that was passed in. 1912 1913const char * sourceBegin = source; 1914const char * sourceEnd = source + strlen (source); 1915 1916// Look for a version directive in the user-provided source. 1917const char * versionBegin = strstr (source, "#version" ); 1918const char * versionEnd = nullptr ; 1919if (versionBegin) 1920{ 1921// If we found a directive, then scan for the end-of-line 1922// after it, and use that to specify the slice. 1923versionEnd = strchr (versionBegin, '\n' ); 1924if (!versionEnd) 1925{ 1926versionEnd = sourceEnd; 1927} 1928else 1929{ 1930versionEnd = versionEnd + 1 ; 1931} 1932} 1933else 1934{ 1935// If we didn't find a directive, then treat it as being 1936// a zero-byte slice at the start of the string 1937versionBegin = sourceBegin; 1938versionEnd = sourceBegin; 1939} 1940 1941enum 1942{ 1943kMaxSourceStringCount = 16 1944}; 1945const GLchar * sourceStrings[kMaxSourceStringCount]; 1946GLint sourceStringLengths[kMaxSourceStringCount]; 1947 1948int sourceStringCount = 0 ; 1949 1950const char * stagePrelude = "\n" ; 1951switch (stage) 1952{ 1953#define CASE ( NAME ) \ 1954case GL_##NAME##_SHADER: \ 1955stagePrelude = "#define __GLSL_" #NAME "__ 1\n"; \ 1956break 1957 1958CASE ( VERTEX ); 1959CASE ( TESS_CONTROL ); 1960CASE ( TESS_EVALUATION ); 1961CASE ( GEOMETRY ); 1962CASE ( FRAGMENT ); 1963CASE ( COMPUTE ); 1964 1965#undef CASE 1966} 1967 1968const char * prelude = "#define __GLSL__ 1\n" ; 1969 1970#define ADD_SOURCE_STRING_SPAN ( BEGIN , END ) \ 1971sourceStrings[sourceStringCount] = BEGIN; \ 1972sourceStringLengths[sourceStringCount++] = GLint(END - BEGIN) /* end */ 1973 1974#define ADD_SOURCE_STRING ( BEGIN ) \ 1975sourceStrings[sourceStringCount] = BEGIN; \ 1976sourceStringLengths[sourceStringCount++] = GLint(strlen(BEGIN)) /* end */ 1977 1978ADD_SOURCE_STRING_SPAN (versionBegin, versionEnd); 1979ADD_SOURCE_STRING (stagePrelude); 1980ADD_SOURCE_STRING (prelude); 1981ADD_SOURCE_STRING_SPAN (sourceBegin, versionBegin); 1982ADD_SOURCE_STRING_SPAN (versionEnd, sourceEnd); 1983 1984auto shaderID = glCreateShader (stage); 1985glShaderSource (shaderID, sourceStringCount, & sourceStrings[ 0 ], & sourceStringLengths[ 0 ]); 1986glCompileShader (shaderID); 1987 1988GLint success = GL_FALSE ; 1989glGetShaderiv (shaderID, GL_COMPILE_STATUS , & success); 1990if (!success) 1991{ 1992int maxSize = 0 ; 1993glGetShaderiv (shaderID, GL_INFO_LOG_LENGTH , & maxSize); 1994 1995auto infoBuffer = ( char * ) malloc (maxSize); 1996 1997int infoSize = 0 ; 1998glGetShaderInfoLog (shaderID, maxSize, & infoSize, infoBuffer); 1999if (infoSize > 0 ) 2000{ 2001fprintf (stderr, "%s" , infoBuffer); 2002:: OutputDebugStringA (infoBuffer); 2003} 2004 2005glDeleteShader (shaderID); 2006return 0 ; 2007} 2008 2009return shaderID; 2010} 2011 2012// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!! 2013 2014#ifdef _WIN32 2015LRESULT CALLBACK WindowProc ( _In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam) 2016{ 2017return DefWindowProc (hwnd, uMsg, wParam, lParam); 2018} 2019#endif 2020 2021WindowHandle createWindow () 2022{ 2023WindowHandle window = {}; 2024#ifdef _WIN32 2025const wchar_t className[] = L"OpenGLContextWindow" ; 2026static bool windowClassRegistered = false; 2027HINSTANCE hInstance = GetModuleHandle ( NULL ); 2028if (!windowClassRegistered) 2029{ 2030windowClassRegistered = true; 2031WNDCLASS wc = {}; 2032wc. lpfnWndProc = WindowProc; 2033wc. hInstance = hInstance; 2034wc. lpszClassName = className; 2035RegisterClass ( & wc); 2036} 2037 2038HWND hwnd = CreateWindowEx ( 20390 , // Optional window styles. 2040className, // Window class 2041L"GLWindow" , // Window text 2042WS_OVERLAPPEDWINDOW , // Window style 2043// Size and position 2044CW_USEDEFAULT , 2045CW_USEDEFAULT , 2046CW_USEDEFAULT , 2047CW_USEDEFAULT , 2048NULL , // Parent window 2049NULL , // Menu 2050hInstance, // Instance handle 2051NULL // Additional application data 2052); 2053 2054if (hwnd == NULL ) 2055{ 2056return window; 2057} 2058window = WindowHandle :: FromHwnd (hwnd); 2059#endif 2060return window; 2061} 2062 2063void destroyWindow ( WindowHandle window) 2064{ 2065#ifdef _WIN32 2066DestroyWindow (( HWND )window. handleValues [ 0 ]); 2067#endif 2068} 2069 2070GLDevice :: GLDevice () 2071{ 2072m_weakRenderer = new WeakSink < GLDevice > (this); 2073} 2074 2075GLDevice ::~GLDevice() 2076{ 2077// We can destroy things whilst in this state 2078m_currentPipelineState. setNull (); 2079m_currentFramebuffer. setNull (); 2080if (glDeleteVertexArrays) 2081{ 2082glDeleteVertexArrays ( 1 , & m_vao); 2083} 2084if (m_glContext) 2085{ 2086wglDeleteContext (m_glContext); 2087} 2088destroyWindow (m_windowHandle); 2089 2090// By resetting the weak pointer, other objects accessing through WeakSink<GLDevice> will no 2091// longer be able to access this object which is entering a 'being destroyed' to 'destroyed' 2092// state 2093if (m_weakRenderer) 2094{ 2095SLANG_ASSERT (m_weakRenderer -> get () == this); 2096m_weakRenderer -> detach (); 2097} 2098} 2099 2100HGLRC GLDevice :: createGLContext ( HDC hdc) 2101{ 2102PIXELFORMATDESCRIPTOR pixelFormatDesc = { sizeof ( PIXELFORMATDESCRIPTOR )}; 2103pixelFormatDesc. nVersion = 1 ; 2104pixelFormatDesc. dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER ; 2105pixelFormatDesc. iPixelType = PFD_TYPE_RGBA ; 2106pixelFormatDesc. cColorBits = 32 ; 2107pixelFormatDesc. cDepthBits = 24 ; 2108pixelFormatDesc. cStencilBits = 8 ; 2109pixelFormatDesc. iLayerType = PFD_MAIN_PLANE ; 2110int pixelFormatIndex = ChoosePixelFormat (hdc, & pixelFormatDesc); 2111SetPixelFormat (hdc, pixelFormatIndex, & pixelFormatDesc); 2112 2113int attributeList[ 5 ]; 2114 2115attributeList[ 0 ] = WGL_CONTEXT_MAJOR_VERSION_ARB ; 2116attributeList[ 1 ] = 4 ; 2117attributeList[ 2 ] = WGL_CONTEXT_MINOR_VERSION_ARB ; 2118attributeList[ 3 ] = 3 ; 2119attributeList[ 4 ] = 0 ; 2120 2121HGLRC newGLContext = wglCreateContextAttribsARB (hdc, m_glContext, attributeList); 2122return newGLContext; 2123} 2124 2125SLANG_NO_THROW Result SLANG_MCALL GLDevice :: initialize ( const Desc & desc) 2126{ 2127SLANG_RETURN_ON_FAIL (slangContext. initialize ( 2128desc. slang , 2129desc. extendedDescCount , 2130desc. extendedDescs , 2131SLANG_GLSL , 2132"glsl_440" , 2133makeArray (slang:: PreprocessorMacroDesc { "__GL__" , "1" }). getView ())); 2134 2135SLANG_RETURN_ON_FAIL ( RendererBase :: initialize (desc)); 2136 2137// Initialize DeviceInfo 2138{ 2139m_info. deviceType = DeviceType ::OpenGl; 2140m_info. bindingStyle = BindingStyle ::OpenGl; 2141m_info. projectionStyle = ProjectionStyle ::OpenGl; 2142m_info. apiName = "OpenGL" ; 2143static const float kIdentity[] = { 1 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 1 }; 2144:: memcpy (m_info. identityProjectionMatrix , kIdentity, sizeof (kIdentity)); 2145} 2146 2147m_windowHandle = createWindow (); 2148m_desc = desc; 2149 2150m_hdc = :: GetDC (( HWND )m_windowHandle. handleValues [ 0 ]); 2151 2152PIXELFORMATDESCRIPTOR pixelFormatDesc = { sizeof ( PIXELFORMATDESCRIPTOR )}; 2153pixelFormatDesc. nVersion = 1 ; 2154pixelFormatDesc. dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER ; 2155pixelFormatDesc. iPixelType = PFD_TYPE_RGBA ; 2156pixelFormatDesc. cColorBits = 32 ; 2157pixelFormatDesc. cDepthBits = 24 ; 2158pixelFormatDesc. cStencilBits = 8 ; 2159pixelFormatDesc. iLayerType = PFD_MAIN_PLANE ; 2160 2161int pixelFormatIndex = ChoosePixelFormat (m_hdc, & pixelFormatDesc); 2162SetPixelFormat (m_hdc, pixelFormatIndex, & pixelFormatDesc); 2163m_glContext = wglCreateContext (m_hdc); 2164wglMakeCurrent (m_hdc, m_glContext); 2165 2166auto renderer = glGetString ( GL_RENDERER ); 2167m_info. adapterName = ( char * )renderer; 2168 2169if (desc. adapterLUID ) 2170{ 2171return SLANG_E_INVALID_ARG ; 2172} 2173 2174if (m_desc. nvapiExtnSlot >= 0 ) 2175{ 2176if ( SLANG_FAILED ( NVAPIUtil :: initialize ())) 2177{ 2178return SLANG_E_NOT_AVAILABLE ; 2179} 2180} 2181 2182 2183auto extensions = glGetString ( GL_EXTENSIONS ); 2184 2185// Load each of our extension functions by name 2186 2187#define LOAD_GL_EXTENSION_FUNC ( NAME , TYPE ) NAME = (TYPE)wglGetProcAddress(#NAME); 2188MAP_GL_EXTENSION_FUNCS ( LOAD_GL_EXTENSION_FUNC ) 2189MAP_WGL_EXTENSION_FUNCS ( LOAD_GL_EXTENSION_FUNC ) 2190#undef LOAD_GL_EXTENSION_FUNC 2191 2192wglMakeCurrent (m_hdc, 0 ); 2193wglDeleteContext (m_glContext); 2194m_glContext = 0 ; 2195 2196if (!wglCreateContextAttribsARB) 2197{ 2198return SLANG_FAIL ; 2199} 2200 2201m_glContext = createGLContext (m_hdc); 2202 2203if (m_glContext == NULL ) 2204{ 2205return SLANG_FAIL ; 2206} 2207wglMakeCurrent (m_hdc, m_glContext); 2208 2209glDisable ( GL_DEPTH_TEST ); 2210glDisable ( GL_CULL_FACE ); 2211 2212if (!glGenVertexArrays) 2213return SLANG_FAIL ; 2214 2215glGenVertexArrays ( 1 , & m_vao); 2216glBindVertexArray (m_vao); 2217 2218if (glDebugMessageCallback) 2219{ 2220glEnable ( GL_DEBUG_OUTPUT ); 2221glDebugMessageCallback (staticDebugCallback, this); 2222} 2223 2224return SLANG_OK ; 2225} 2226 2227void GLDevice :: clearFrame ( uint32_t mask, bool clearDepth, bool clearStencil) 2228{ 2229uint32_t clearMask = 0 ; 2230if (clearDepth) 2231{ 2232clearMask |= GL_DEPTH_BUFFER_BIT ; 2233glClearDepth (m_currentFramebuffer -> m_depthStencilClearValue . depth ); 2234} 2235if (clearStencil) 2236{ 2237clearMask |= GL_STENCIL_BUFFER_BIT ; 2238glClearStencil (m_currentFramebuffer -> m_depthStencilClearValue . stencil ); 2239} 2240if (clearMask) 2241{ 2242// If clear value for all attachments are the same, issue one `glClear` command. 2243if (m_currentFramebuffer -> m_sameClearValues && 2244m_currentFramebuffer -> m_colorClearValues . getCount () > 0 ) 2245{ 2246ShortList < GLenum > clearBuffers; 2247auto clearColor = m_currentFramebuffer -> m_colorClearValues [ 0 ]; 2248glClearColor ( 2249clearColor. floatValues [ 0 ], 2250clearColor. floatValues [ 1 ], 2251clearColor. floatValues [ 2 ], 2252clearColor. floatValues [ 3 ]); 2253for ( Index i = 0 ; i < m_currentFramebuffer -> m_colorClearValues . getCount (); i ++ ) 2254{ 2255if (mask & uint32_t ( 1 << i)) 2256clearBuffers. add ( GLenum ( GL_COLOR_ATTACHMENT0 + i)); 2257} 2258if (clearBuffers. getCount ()) 2259{ 2260glDrawBuffers ( 2261( GLsizei )clearBuffers. getCount (), 2262clearBuffers. getArrayView (). getBuffer ()); 2263clearMask |= GL_COLOR_BUFFER_BIT ; 2264} 2265glClear (clearMask); 2266glDrawBuffers ( 2267( GLsizei )m_currentFramebuffer -> m_drawBuffers . getCount (), 2268m_currentFramebuffer -> m_drawBuffers . getArrayView (). getBuffer ()); 2269return ; 2270} 2271// If clear values are different, clear attachments separately. 2272for ( Index i = 0 ; i < m_currentFramebuffer -> m_colorClearValues . getCount (); i ++ ) 2273{ 2274if (mask & uint32_t ( 1 << i)) 2275{ 2276GLenum drawBuffer = GLenum ( GL_COLOR_ATTACHMENT0 + i); 2277glDrawBuffers ( 1 , & drawBuffer); 2278auto clearColor = m_currentFramebuffer -> m_colorClearValues [i]; 2279glClearColor ( 2280clearColor. floatValues [ 0 ], 2281clearColor. floatValues [ 1 ], 2282clearColor. floatValues [ 2 ], 2283clearColor. floatValues [ 3 ]); 2284glClear ( GL_COLOR_BUFFER_BIT ); 2285} 2286} 2287// Clear depth/stencil attachments. 2288glClear (clearMask); 2289glDrawBuffers ( 2290( GLsizei )m_currentFramebuffer -> m_drawBuffers . getCount (), 2291m_currentFramebuffer -> m_drawBuffers . getArrayView (). getBuffer ()); 2292} 2293} 2294 2295SLANG_NO_THROW Result SLANG_MCALL GLDevice :: createSwapchain ( 2296const ISwapchain :: Desc & desc, 2297WindowHandle window, 2298ISwapchain ** outSwapchain) 2299{ 2300RefPtr < SwapchainImpl > swapchain = new SwapchainImpl (); 2301SLANG_RETURN_ON_FAIL (swapchain -> init (this, desc, window)); 2302returnComPtr (outSwapchain, swapchain); 2303wglMakeCurrent (m_hdc, m_glContext); 2304return SLANG_OK ; 2305} 2306 2307SLANG_NO_THROW Result SLANG_MCALL GLDevice :: createFramebufferLayout ( 2308const IFramebufferLayout :: Desc & desc, 2309IFramebufferLayout ** outLayout) 2310{ 2311RefPtr < FramebufferLayoutImpl > layout = new FramebufferLayoutImpl (); 2312layout -> m_renderTargets . setCount (desc. renderTargetCount ); 2313for ( GfxIndex i = 0 ; i < desc. renderTargetCount ; i ++ ) 2314{ 2315layout -> m_renderTargets [i] = desc. renderTargets [i]; 2316} 2317 2318if (desc. depthStencil ) 2319{ 2320layout -> m_hasDepthStencil = true; 2321layout -> m_depthStencil = * desc. depthStencil ; 2322} 2323else 2324{ 2325layout -> m_hasDepthStencil = false; 2326} 2327returnComPtr (outLayout, layout); 2328return SLANG_OK ; 2329} 2330 2331SLANG_NO_THROW Result SLANG_MCALL 2332GLDevice :: createFramebuffer ( const IFramebuffer :: Desc & desc, IFramebuffer ** outFramebuffer) 2333{ 2334RefPtr < FramebufferImpl > framebuffer = new FramebufferImpl (m_weakRenderer); 2335framebuffer -> renderTargetViews . setCount (desc. renderTargetCount ); 2336for ( GfxIndex i = 0 ; i < desc. renderTargetCount ; i ++ ) 2337{ 2338framebuffer -> renderTargetViews [i] = 2339static_cast < TextureViewImpl *> (desc. renderTargetViews [i]); 2340} 2341framebuffer -> depthStencilView = static_cast < TextureViewImpl *> (desc. depthStencilView ); 2342framebuffer -> createGLFramebuffer (); 2343returnComPtr (outFramebuffer, framebuffer); 2344return SLANG_OK ; 2345} 2346 2347void GLDevice :: setFramebuffer ( IFramebuffer * frameBuffer) 2348{ 2349m_currentFramebuffer = static_cast < FramebufferImpl *> (frameBuffer); 2350} 2351 2352void GLDevice :: setStencilReference ( uint32_t referenceValue) 2353{ 2354m_stencilRef = referenceValue; 2355// TODO: actually set the stencil state. 2356} 2357 2358void GLDevice :: copyBuffer ( 2359IBufferResource * dst, 2360Offset dstOffset, 2361IBufferResource * src, 2362Offset srcOffset, 2363Size size) 2364{ 2365auto dstImpl = static_cast < BufferResourceImpl *> (dst); 2366auto srcImpl = static_cast < BufferResourceImpl *> (src); 2367glBindBuffer ( GL_COPY_READ_BUFFER , srcImpl -> m_handle ); 2368glBindBuffer ( GL_COPY_WRITE_BUFFER , dstImpl -> m_handle ); 2369glCopyBufferSubData ( GL_COPY_READ_BUFFER , GL_COPY_WRITE_BUFFER , srcOffset, dstOffset, size); 2370} 2371 2372SLANG_NO_THROW Result SLANG_MCALL GLDevice :: readTextureResource ( 2373ITextureResource * texture, 2374ResourceState state, 2375ISlangBlob ** outBlob, 2376Size * outRowPitch, 2377Size * outPixelSize) 2378{ 2379SLANG_UNUSED (state); 2380auto resource = static_cast < TextureResourceImpl *> (texture); 2381auto size = resource -> getDesc () -> size ; 2382size_t requiredSize = size. width * size. height * sizeof ( uint32_t ); 2383if (outRowPitch) 2384* outRowPitch = size. width * sizeof ( uint32_t ); 2385if (outPixelSize) 2386* outPixelSize = sizeof ( uint32_t ); 2387 2388List < uint8_t > blobData; 2389 2390blobData. setCount (requiredSize); 2391auto buffer = blobData. begin (); 2392glBindTexture (resource -> m_target , resource -> m_handle ); 2393glGetTexImage (resource -> m_target , 0 , GL_RGBA , GL_UNSIGNED_BYTE , buffer); 2394 2395// Flip pixels vertically in-place. 2396for ( int y = 0 ; y < size. height / 2 ; y ++ ) 2397{ 2398for ( int x = 0 ; x < size. width ; x ++ ) 2399{ 2400std:: swap ( 2401* (( uint32_t * )buffer + y * size. width + x), 2402* (( uint32_t * )buffer + (size. height - y - 1 ) * size. width + x)); 2403} 2404} 2405 2406auto blob = ListBlob :: moveCreate (blobData); 2407returnComPtr (outBlob, blob); 2408return SLANG_OK ; 2409} 2410 2411SLANG_NO_THROW Result SLANG_MCALL GLDevice :: createTextureResource ( 2412const ITextureResource :: Desc & descIn, 2413const ITextureResource :: SubresourceData * initData, 2414ITextureResource ** outResource) 2415{ 2416TextureResource :: Desc srcDesc = fixupTextureDesc (descIn); 2417 2418GlPixelFormat pixelFormat = _getGlPixelFormat (srcDesc. format ); 2419if (pixelFormat == GlPixelFormat ::Unknown) 2420{ 2421return SLANG_FAIL ; 2422} 2423 2424const GlPixelFormatInfo & info = s_pixelFormatInfos[ int (pixelFormat)]; 2425 2426const GLint internalFormat = info. internalFormat ; 2427const GLenum format = info. format ; 2428const GLenum formatType = info. formatType ; 2429 2430RefPtr < TextureResourceImpl > texture( new TextureResourceImpl (srcDesc, m_weakRenderer)); 2431 2432GLenum target = 0 ; 2433GLuint handle = 0 ; 2434glGenTextures ( 1 , & handle); 2435 2436const int effectiveArraySize = calcEffectiveArraySize (srcDesc); 2437 2438// Set on texture so will be freed if failure 2439texture -> m_handle = handle; 2440 2441// TODO: The logic below seems to be ignoring the row/layer stride of 2442// the subresources that have been passed in, despite OpenGL having 2443// the ability to set the image unpack stride, etc. 2444 2445switch (srcDesc. type ) 2446{ 2447case IResource :: Type ::Texture1D: 2448{ 2449if (srcDesc. arraySize > 0 ) 2450{ 2451target = GL_TEXTURE_1D_ARRAY ; 2452glBindTexture (target, handle); 2453 2454int slice = 0 ; 2455for ( int i = 0 ; i < effectiveArraySize; i ++ ) 2456{ 2457for ( int j = 0 ; j < srcDesc. numMipLevels ; j ++ ) 2458{ 2459// TODO: Double-check this logic - we are passing in `i` as the height? 2460glTexImage2D ( 2461target, 2462j, 2463internalFormat, 2464Math :: Max ( 1 , srcDesc. size . width >> j), 2465i, 24660 , 2467format, 2468formatType, 2469initData ? initData[slice ++ ]. data : nullptr ); 2470} 2471} 2472} 2473else 2474{ 2475target = GL_TEXTURE_1D ; 2476glBindTexture (target, handle); 2477for ( int i = 0 ; i < srcDesc. numMipLevels ; i ++ ) 2478{ 2479glTexImage1D ( 2480target, 2481i, 2482internalFormat, 2483Math :: Max ( 1 , srcDesc. size . width >> i), 24840 , 2485format, 2486formatType, 2487initData ? initData[i]. data : nullptr ); 2488} 2489} 2490break ; 2491} 2492case IResource :: Type ::TextureCube: 2493case IResource :: Type ::Texture2D: 2494{ 2495if (srcDesc. arraySize > 0 ) 2496{ 2497if (srcDesc. type == IResource :: Type ::TextureCube) 2498{ 2499target = GL_TEXTURE_CUBE_MAP_ARRAY ; 2500} 2501else 2502{ 2503target = GL_TEXTURE_2D_ARRAY ; 2504} 2505 2506glBindTexture (target, handle); 2507 2508int slice = 0 ; 2509for ( int i = 0 ; i < effectiveArraySize; i ++ ) 2510{ 2511for ( int j = 0 ; j < srcDesc. numMipLevels ; j ++ ) 2512{ 2513const void * dataPtr = nullptr ; 2514if (initData) 2515{ 2516dataPtr = initData[slice]. data ; 2517++ slice; 2518} 2519glTexImage3D ( 2520target, 2521j, 2522internalFormat, 2523Math :: Max ( 1 , srcDesc. size . width >> j), 2524Math :: Max ( 1 , srcDesc. size . height >> j), 2525slice, 25260 , 2527format, 2528formatType, 2529dataPtr); 2530} 2531} 2532} 2533else 2534{ 2535if (srcDesc. type == IResource :: Type ::TextureCube) 2536{ 2537target = GL_TEXTURE_CUBE_MAP ; 2538glBindTexture (target, handle); 2539 2540int slice = 0 ; 2541for ( int j = 0 ; j < 6 ; j ++ ) 2542{ 2543for ( int i = 0 ; i < srcDesc. numMipLevels ; i ++ ) 2544{ 2545glTexImage2D ( 2546GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, 2547i, 2548internalFormat, 2549Math :: Max ( 1 , srcDesc. size . width >> i), 2550Math :: Max ( 1 , srcDesc. size . height >> i), 25510 , 2552format, 2553formatType, 2554initData ? initData[slice ++ ]. data : nullptr ); 2555} 2556} 2557} 2558else 2559{ 2560target = GL_TEXTURE_2D ; 2561glBindTexture (target, handle); 2562for ( int i = 0 ; i < srcDesc. numMipLevels ; i ++ ) 2563{ 2564glTexImage2D ( 2565target, 2566i, 2567internalFormat, 2568Math :: Max ( 1 , srcDesc. size . width >> i), 2569Math :: Max ( 1 , srcDesc. size . height >> i), 25700 , 2571format, 2572formatType, 2573initData ? initData[i]. data : nullptr ); 2574} 2575} 2576} 2577break ; 2578} 2579case IResource :: Type ::Texture3D: 2580{ 2581target = GL_TEXTURE_3D ; 2582glBindTexture (target, handle); 2583for ( int i = 0 ; i < srcDesc. numMipLevels ; i ++ ) 2584{ 2585glTexImage3D ( 2586target, 2587i, 2588internalFormat, 2589Math :: Max ( 1 , srcDesc. size . width >> i), 2590Math :: Max ( 1 , srcDesc. size . height >> i), 2591Math :: Max ( 1 , srcDesc. size . depth >> i), 25920 , 2593format, 2594formatType, 2595initData ? initData[i]. data : nullptr ); 2596} 2597break ; 2598} 2599default : 2600return SLANG_FAIL ; 2601} 2602 2603glTexParameteri (target, GL_TEXTURE_WRAP_S , GL_REPEAT ); 2604glTexParameteri (target, GL_TEXTURE_WRAP_T , GL_REPEAT ); 2605glTexParameteri (target, GL_TEXTURE_WRAP_R , GL_REPEAT ); 2606 2607// Assume regular sampling (might be superseded - if a combined sampler wanted) 2608glTexParameteri (target, GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_LINEAR ); 2609glTexParameteri (target, GL_TEXTURE_MAG_FILTER , GL_LINEAR ); 2610glTexParameterf (target, GL_TEXTURE_MAX_ANISOTROPY_EXT , 8.0f ); 2611 2612texture -> m_target = target; 2613 2614returnComPtr (outResource, texture); 2615return SLANG_OK ; 2616} 2617 2618static GLenum _calcUsage ( ResourceState state) 2619{ 2620switch (state) 2621{ 2622case ResourceState ::ConstantBuffer: 2623return GL_DYNAMIC_DRAW ; 2624default : 2625return GL_STATIC_READ ; 2626} 2627} 2628 2629static GLenum _calcTarget ( ResourceState state) 2630{ 2631switch (state) 2632{ 2633case ResourceState ::ConstantBuffer: 2634return GL_UNIFORM_BUFFER ; 2635default : 2636return GL_SHADER_STORAGE_BUFFER ; 2637} 2638} 2639 2640SLANG_NO_THROW Result SLANG_MCALL GLDevice :: createBufferResource ( 2641const IBufferResource :: Desc & descIn, 2642const void * initData, 2643IBufferResource ** outResource) 2644{ 2645BufferResource :: Desc desc = fixupBufferDesc (descIn); 2646 2647const GLenum target = _calcTarget (desc. defaultState ); 2648const GLenum usage = _calcUsage (desc. defaultState ); 2649 2650GLuint bufferID = 0 ; 2651glGenBuffers ( 1 , & bufferID); 2652glBindBuffer (target, bufferID); 2653 2654glBufferData (target, descIn. sizeInBytes , initData, usage); 2655 2656RefPtr < BufferResourceImpl > resourceImpl = 2657new BufferResourceImpl (desc, m_weakRenderer, bufferID, target); 2658returnComPtr (outResource, resourceImpl); 2659return SLANG_OK ; 2660} 2661 2662SLANG_NO_THROW Result SLANG_MCALL 2663GLDevice :: createSamplerState ( ISamplerState :: Desc const & desc, ISamplerState ** outSampler) 2664{ 2665GLuint samplerID; 2666glCreateSamplers ( 1 , & samplerID); 2667 2668RefPtr < SamplerStateImpl > samplerImpl = new SamplerStateImpl (); 2669samplerImpl -> m_samplerID = samplerID; 2670returnComPtr (outSampler, samplerImpl); 2671return SLANG_OK ; 2672} 2673 2674SLANG_NO_THROW Result SLANG_MCALL GLDevice :: createTextureView ( 2675ITextureResource * texture, 2676IResourceView :: Desc const & desc, 2677IResourceView ** outView) 2678{ 2679auto resourceImpl = static_cast < TextureResourceImpl *> (texture); 2680 2681// TODO: actually do something? 2682 2683RefPtr < TextureViewImpl > viewImpl = new TextureViewImpl (); 2684viewImpl -> m_resource = resourceImpl; 2685viewImpl -> m_textureID = resourceImpl -> m_handle ; 2686viewImpl -> type = ResourceViewImpl :: Type ::Texture; 2687viewImpl -> m_target = resourceImpl -> m_target ; 2688viewImpl -> m_desc = desc; 2689 2690if (desc. type == IResourceView :: Type ::ShaderResource) 2691{ 2692viewImpl -> access = GL_READ_ONLY ; 2693viewImpl -> textureViewType = TextureViewImpl :: TextureViewType ::Texture; 2694} 2695else 2696{ 2697viewImpl -> access = GL_READ_WRITE ; 2698viewImpl -> textureViewType = TextureViewImpl :: TextureViewType ::Image; 2699} 2700const GlPixelFormatInfo & info = s_pixelFormatInfos[ int ( _getGlPixelFormat (desc. format ))]; 2701viewImpl -> format = info. internalFormat ; 2702viewImpl -> layered = GL_TRUE ; 2703viewImpl -> level = 0 ; 2704viewImpl -> layer = 0 ; 2705returnComPtr (outView, viewImpl); 2706return SLANG_OK ; 2707} 2708 2709SLANG_NO_THROW Result SLANG_MCALL GLDevice :: createBufferView ( 2710IBufferResource * buffer, 2711IBufferResource * counterBuffer, 2712IResourceView :: Desc const & desc, 2713IResourceView ** outView) 2714{ 2715auto resourceImpl = ( BufferResourceImpl * )buffer; 2716 2717// TODO: actually do something? 2718 2719RefPtr < BufferViewImpl > viewImpl = new BufferViewImpl (); 2720viewImpl -> type = ResourceViewImpl :: Type ::Buffer; 2721viewImpl -> m_resource = resourceImpl; 2722viewImpl -> m_bufferID = resourceImpl -> m_handle ; 2723viewImpl -> m_desc = desc; 2724 2725returnComPtr (outView, viewImpl); 2726return SLANG_OK ; 2727} 2728 2729SLANG_NO_THROW Result SLANG_MCALL 2730GLDevice :: createInputLayout ( IInputLayout :: Desc const & desc, IInputLayout ** outLayout) 2731{ 2732RefPtr < InputLayoutImpl > inputLayout = new InputLayoutImpl ; 2733 2734auto inputElements = desc. inputElements ; 2735Int inputElementCount = desc. inputElementCount ; 2736inputLayout -> m_attributeCount = inputElementCount; 2737for ( Int ii = 0 ; ii < inputElementCount; ++ ii) 2738{ 2739auto & inputAttr = inputElements[ii]; 2740auto & glAttr = inputLayout -> m_attributes [ii]; 2741 2742glAttr. streamIndex = ( GLuint )inputAttr. bufferSlotIndex ; 2743glAttr. format = getVertexAttributeFormat (inputAttr. format ); 2744glAttr. offset = ( GLsizei )inputAttr. offset ; 2745} 2746 2747Int inputStreamCount = desc. vertexStreamCount ; 2748inputLayout -> m_streamCount = inputStreamCount; 2749for ( Int i = 0 ; i < inputStreamCount; ++ i) 2750{ 2751inputLayout -> m_streams [i]. stride = desc. vertexStreams [i]. stride ; 2752} 2753 2754returnComPtr (outLayout, inputLayout); 2755return SLANG_OK ; 2756} 2757 2758void * GLDevice :: map ( IBufferResource * bufferIn, MapFlavor flavor) 2759{ 2760BufferResourceImpl * buffer = static_cast < BufferResourceImpl *> (bufferIn); 2761 2762// GLenum target = GL_UNIFORM_BUFFER; 2763 2764GLuint access = 0 ; 2765switch (flavor) 2766{ 2767case MapFlavor ::WriteDiscard: 2768case MapFlavor ::HostWrite: 2769access = GL_WRITE_ONLY ; 2770break ; 2771case MapFlavor ::HostRead: 2772access = GL_READ_ONLY ; 2773break ; 2774} 2775 2776glBindBuffer (buffer -> m_target , buffer -> m_handle ); 2777 2778return glMapBuffer (buffer -> m_target , access); 2779} 2780 2781void GLDevice :: unmap ( IBufferResource * bufferIn, size_t offsetWritten, size_t sizeWritten) 2782{ 2783SLANG_UNUSED (offsetWritten); 2784SLANG_UNUSED (sizeWritten); 2785BufferResourceImpl * buffer = static_cast < BufferResourceImpl *> (bufferIn); 2786glUnmapBuffer (buffer -> m_target ); 2787} 2788 2789void GLDevice :: setPrimitiveTopology ( PrimitiveTopology topology) 2790{ 2791GLenum glTopology = 0 ; 2792switch (topology) 2793{ 2794#define CASE ( NAME , VALUE ) \ 2795case PrimitiveTopology::NAME: \ 2796glTopology = VALUE; \ 2797break 2798 2799CASE (TriangleList, GL_TRIANGLES ); 2800 2801#undef CASE 2802} 2803m_boundPrimitiveTopology = glTopology; 2804} 2805 2806void GLDevice :: setVertexBuffers ( 2807GfxIndex startSlot, 2808GfxCount slotCount, 2809IBufferResource * const * buffers, 2810const Offset * offsets) 2811{ 2812for ( UInt ii = 0 ; ii < slotCount; ++ ii) 2813{ 2814UInt slot = startSlot + ii; 2815 2816BufferResourceImpl * buffer = static_cast < BufferResourceImpl *> (buffers[ii]); 2817GLuint bufferID = buffer ? buffer -> m_handle : 0 ; 2818 2819m_boundVertexStreamBuffers[slot] = bufferID; 2820m_boundVertexStreamOffsets[slot] = offsets[ii]; 2821} 2822} 2823 2824void GLDevice :: setIndexBuffer ( IBufferResource * buffer, Format indexFormat, Offset offset) 2825{ 2826auto bufferImpl = static_cast < BufferResourceImpl *> (buffer); 2827m_boundIndexBuffer = bufferImpl -> m_handle ; 2828m_boundIndexBufferOffset = offset; 2829m_boundIndexBufferSize = bufferImpl -> m_size ; 2830} 2831 2832void GLDevice :: setViewports ( GfxCount count, Viewport const * viewports) 2833{ 2834assert (count == 1 ); 2835auto viewport = viewports[ 0 ]; 2836glViewport ( 2837( GLint )viewport. originX , 2838( GLint )viewport. originY , 2839( GLsizei )viewport. extentX , 2840( GLsizei )viewport. extentY ); 2841glDepthRange (viewport. minZ , viewport. maxZ ); 2842} 2843 2844void GLDevice :: setScissorRects ( GfxCount count, ScissorRect const * rects) 2845{ 2846assert (count <= 1 ); 2847if (count) 2848{ 2849// TODO: this isn't goign to be quite right because of the 2850// flipped coordinate system in GL. 2851// 2852// The best way around this is probably to *always* render 2853// things internally into textures with "flipped" conventions, 2854// and then only deal with the flipping as part of a final 2855// "present" step that copies to the primary back-buffer. 2856// 2857auto rect = rects[ 0 ]; 2858glScissor ( 2859GLint (rect. minX ), 2860GLint (rect. minY ), 2861GLsizei (rect. maxX - rect. minX ), 2862GLsizei (rect. maxY - rect. minY )); 2863 2864glEnable ( GL_SCISSOR_TEST ); 2865} 2866else 2867{ 2868glDisable ( GL_SCISSOR_TEST ); 2869} 2870} 2871 2872void GLDevice :: setPipelineState ( IPipelineState * state) 2873{ 2874auto pipelineStateImpl = static_cast < PipelineStateImpl *> (state); 2875 2876m_currentPipelineState = pipelineStateImpl; 2877 2878auto program = static_cast < ShaderProgramImpl *> (pipelineStateImpl -> m_program . Ptr ()); 2879GLuint programID = program ? program -> m_id : 0 ; 2880glUseProgram (programID); 2881} 2882 2883void GLDevice :: draw ( GfxCount vertexCount, GfxIndex startVertex = 0 ) 2884{ 2885flushStateForDraw (); 2886 2887glDrawArrays (m_boundPrimitiveTopology, ( GLint )startVertex, ( GLsizei )vertexCount); 2888} 2889 2890void GLDevice :: drawIndexed ( GfxCount indexCount, GfxIndex startIndex, GfxIndex baseVertex) 2891{ 2892flushStateForDraw (); 2893 2894glDrawElementsBaseVertex ( 2895m_boundPrimitiveTopology, 2896( GLsizei )indexCount, 2897GL_UNSIGNED_INT , 2898( GLvoid * )(startIndex * sizeof ( uint32_t )), 2899( GLint )baseVertex); 2900} 2901 2902void GLDevice :: drawInstanced ( 2903GfxCount vertexCount, 2904GfxCount instanceCount, 2905GfxIndex startVertex, 2906GfxIndex startInstanceLocation) 2907{ 2908SLANG_UNIMPLEMENTED_X ( "drawInstanced" ); 2909} 2910 2911void GLDevice :: drawIndexedInstanced ( 2912GfxCount indexCount, 2913GfxCount instanceCount, 2914GfxIndex startIndexLocation, 2915GfxIndex baseVertexLocation, 2916GfxIndex startInstanceLocation) 2917{ 2918SLANG_UNIMPLEMENTED_X ( "drawIndexedInstanced" ); 2919} 2920 2921void GLDevice :: dispatchCompute ( int x, int y, int z) 2922{ 2923glDispatchCompute (x, y, z); 2924} 2925 2926Result GLDevice :: createProgram ( 2927const IShaderProgram :: Desc & desc, 2928IShaderProgram ** outProgram, 2929ISlangBlob ** outDiagnosticBlob) 2930{ 2931if (desc. slangGlobalScope -> getSpecializationParamCount () != 0 ) 2932{ 2933// For a specializable program, we don't invoke any actual slang compilation yet. 2934RefPtr < ShaderProgramImpl > shaderProgram = new ShaderProgramImpl (m_weakRenderer, 0 ); 2935shaderProgram -> init (desc); 2936returnComPtr (outProgram, shaderProgram); 2937return SLANG_OK ; 2938} 2939 2940auto programID = glCreateProgram (); 2941auto programLayout = desc. slangGlobalScope -> getLayout (); 2942ShortList < GLuint > shaderIDs; 2943for ( SlangUInt i = 0 ; i < programLayout -> getEntryPointCount (); i ++ ) 2944{ 2945ComPtr < ISlangBlob > kernelCode; 2946ComPtr < ISlangBlob > diagnostics; 2947auto compileResult = getEntryPointCodeFromShaderCache ( 2948desc. slangGlobalScope , 2949i, 29500 , 2951kernelCode. writeRef (), 2952diagnostics. writeRef ()); 2953if (diagnostics) 2954{ 2955getDebugCallback () -> handleMessage ( 2956compileResult == SLANG_OK ? DebugMessageType ::Warning : DebugMessageType ::Error, 2957DebugMessageSource ::Slang, 2958( char * )diagnostics -> getBufferPointer ()); 2959if (outDiagnosticBlob) 2960returnComPtr (outDiagnosticBlob, diagnostics); 2961} 2962SLANG_RETURN_ON_FAIL (compileResult); 2963GLenum glShaderType = 0 ; 2964auto stage = programLayout -> getEntryPointByIndex (i) -> getStage (); 2965switch (stage) 2966{ 2967case SLANG_STAGE_COMPUTE : 2968glShaderType = GL_COMPUTE_SHADER ; 2969break ; 2970case SLANG_STAGE_VERTEX : 2971glShaderType = GL_VERTEX_SHADER ; 2972break ; 2973case SLANG_STAGE_FRAGMENT : 2974glShaderType = GL_FRAGMENT_SHADER ; 2975break ; 2976case SLANG_STAGE_GEOMETRY : 2977glShaderType = GL_GEOMETRY_SHADER ; 2978break ; 2979case SLANG_STAGE_DOMAIN : 2980glShaderType = GL_TESS_CONTROL_SHADER ; 2981break ; 2982case SLANG_STAGE_HULL : 2983glShaderType = GL_TESS_EVALUATION_SHADER ; 2984break ; 2985default : 2986SLANG_ASSERT (! "unsupported shader type." ); 2987break ; 2988} 2989auto shaderID = loadShader (glShaderType, ( char const * )kernelCode -> getBufferPointer ()); 2990shaderIDs. add (shaderID); 2991glAttachShader (programID, shaderID); 2992} 2993glLinkProgram (programID); 2994for ( auto shaderID : shaderIDs) 2995glDeleteShader (shaderID); 2996GLint success = GL_FALSE ; 2997glGetProgramiv (programID, GL_LINK_STATUS , & success); 2998if (!success) 2999{ 3000int maxSize = 0 ; 3001glGetProgramiv (programID, GL_INFO_LOG_LENGTH , & maxSize); 3002 3003auto infoBuffer = ( char * ):: malloc (maxSize); 3004 3005int infoSize = 0 ; 3006glGetProgramInfoLog (programID, maxSize, & infoSize, infoBuffer); 3007if (infoSize > 0 ) 3008{ 3009fprintf (stderr, "%s" , infoBuffer); 3010OutputDebugStringA (infoBuffer); 3011} 3012 3013:: free (infoBuffer); 3014 3015glDeleteProgram (programID); 3016return SLANG_FAIL ; 3017} 3018 3019RefPtr < ShaderProgramImpl > program = new ShaderProgramImpl (m_weakRenderer, programID); 3020program -> slangGlobalScope = desc. slangGlobalScope ; 3021returnComPtr (outProgram, program); 3022return SLANG_OK ; 3023} 3024 3025Result GLDevice :: createGraphicsPipelineState ( 3026const GraphicsPipelineStateDesc & inDesc, 3027IPipelineState ** outState) 3028{ 3029GraphicsPipelineStateDesc desc = inDesc; 3030 3031auto programImpl = ( ShaderProgramImpl * )desc. program ; 3032auto inputLayoutImpl = ( InputLayoutImpl * )desc. inputLayout ; 3033 3034RefPtr < PipelineStateImpl > pipelineStateImpl = new PipelineStateImpl (); 3035pipelineStateImpl -> m_inputLayout = inputLayoutImpl; 3036pipelineStateImpl -> init (desc); 3037returnComPtr (outState, pipelineStateImpl); 3038return SLANG_OK ; 3039} 3040 3041Result GLDevice :: createComputePipelineState ( 3042const ComputePipelineStateDesc & inDesc, 3043IPipelineState ** outState) 3044{ 3045ComputePipelineStateDesc desc = inDesc; 3046 3047auto programImpl = ( ShaderProgramImpl * )desc. program ; 3048 3049RefPtr < PipelineStateImpl > pipelineStateImpl = new PipelineStateImpl (); 3050pipelineStateImpl -> m_program = programImpl; 3051pipelineStateImpl -> init (desc); 3052returnComPtr (outState, pipelineStateImpl); 3053return SLANG_OK ; 3054} 3055 3056Result GLDevice :: createShaderObjectLayout ( 3057slang:: ISession * session, 3058slang:: TypeLayoutReflection * typeLayout, 3059ShaderObjectLayoutBase ** outLayout) 3060{ 3061RefPtr < ShaderObjectLayoutImpl > layout; 3062SLANG_RETURN_ON_FAIL ( 3063ShaderObjectLayoutImpl :: createForElementType (this, session, typeLayout, layout. writeRef ())); 3064returnRefPtrMove (outLayout, layout); 3065return SLANG_OK ; 3066} 3067 3068Result GLDevice :: createShaderObject ( ShaderObjectLayoutBase * layout, IShaderObject ** outObject) 3069{ 3070RefPtr < ShaderObjectImpl > shaderObject; 3071SLANG_RETURN_ON_FAIL ( ShaderObjectImpl :: create ( 3072this, 3073static_cast < ShaderObjectLayoutImpl *> (layout), 3074shaderObject. writeRef ())); 3075returnComPtr (outObject, shaderObject); 3076return SLANG_OK ; 3077} 3078 3079Result GLDevice :: createMutableShaderObject ( 3080ShaderObjectLayoutBase * layout, 3081IShaderObject ** outObject) 3082{ 3083auto layoutImpl = static_cast < ShaderObjectLayoutImpl *> (layout); 3084 3085RefPtr < MutableShaderObjectImpl > result = new MutableShaderObjectImpl (); 3086SLANG_RETURN_ON_FAIL (result -> init (this, layoutImpl)); 3087returnComPtr (outObject, result); 3088 3089return SLANG_OK ; 3090} 3091 3092Result GLDevice :: createRootShaderObject ( IShaderProgram * program, ShaderObjectBase ** outObject) 3093{ 3094auto programImpl = static_cast < ShaderProgramImpl *> (program); 3095RefPtr < RootShaderObjectImpl > shaderObject; 3096RefPtr < RootShaderObjectLayoutImpl > rootLayout; 3097SLANG_RETURN_ON_FAIL ( RootShaderObjectLayoutImpl :: create ( 3098this, 3099programImpl -> slangGlobalScope , 3100programImpl -> slangGlobalScope -> getLayout (), 3101rootLayout. writeRef ())); 3102SLANG_RETURN_ON_FAIL ( 3103RootShaderObjectImpl :: create (this, rootLayout. Ptr (), shaderObject. writeRef ())); 3104returnRefPtrMove (outObject, shaderObject); 3105return SLANG_OK ; 3106} 3107 3108void GLDevice :: bindRootShaderObject ( IShaderObject * shaderObject) 3109{ 3110RootShaderObjectImpl * rootShaderObjectImpl = static_cast < RootShaderObjectImpl *> (shaderObject); 3111RefPtr < PipelineStateBase > specializedPipeline; 3112maybeSpecializePipeline (m_currentPipelineState, rootShaderObjectImpl, specializedPipeline); 3113setPipelineState (specializedPipeline. Ptr ()); 3114 3115m_rootBindingState. imageBindings . clear (); 3116m_rootBindingState. samplerBindings . clear (); 3117m_rootBindingState. textureBindings . clear (); 3118m_rootBindingState. storageBufferBindings . clear (); 3119m_rootBindingState. uniformBufferBindings . clear (); 3120static_cast < ShaderObjectImpl *> (shaderObject) -> bindObject (this, & m_rootBindingState); 3121for ( Index i = 0 ; i < m_rootBindingState. imageBindings . getCount (); i ++ ) 3122{ 3123auto binding = m_rootBindingState. imageBindings [i]; 3124glBindImageTexture ( 3125( GLuint )i, 3126binding -> m_textureID , 3127binding -> level , 3128binding -> layered , 3129binding -> layer , 3130binding -> access , 3131binding -> format ); 3132} 3133for ( Index i = 0 ; i < m_rootBindingState. textureBindings . getCount (); i ++ ) 3134{ 3135glActiveTexture ((GLenum)( GL_TEXTURE0 + i)); 3136auto binding = m_rootBindingState. textureBindings [i]; 3137if (binding) 3138glBindTexture (binding -> m_target , binding -> m_textureID ); 3139glBindSampler (( GLuint )i, m_rootBindingState. samplerBindings [i]); 3140} 3141for ( Index i = 0 ; i < m_rootBindingState. storageBufferBindings . getCount (); i ++ ) 3142{ 3143glBindBufferBase ( 3144GL_SHADER_STORAGE_BUFFER , 3145( GLuint )i, 3146m_rootBindingState. storageBufferBindings [i]); 3147} 3148for ( Index i = 0 ; i < m_rootBindingState. uniformBufferBindings . getCount (); i ++ ) 3149{ 3150glBindBufferBase ( GL_UNIFORM_BUFFER , ( GLuint )i, m_rootBindingState. uniformBufferBindings [i]); 3151} 3152} 3153 3154SlangResult SLANG_MCALL createGLDevice ( const IDevice :: Desc * desc, IDevice ** outRenderer) 3155{ 3156RefPtr < GLDevice > result = new GLDevice (); 3157SLANG_RETURN_ON_FAIL (result -> initialize ( * desc)); 3158returnComPtr (outRenderer, result); 3159return SLANG_OK ; 3160} 3161 3162} // namespace gfx 3163 3164#else 3165 3166namespace gfx 3167{ 3168SlangResult SLANG_MCALL createGLDevice ( const IDevice :: Desc * desc, IDevice ** outRenderer) 3169{ 3170* outRenderer = nullptr ; 3171return SLANG_FAIL ; 3172} 3173} // namespace gfx 3174#endif