#pragma once #include "GfxDevice.h" #if RUSH_RENDER_API == RUSH_RENDER_API_MTL #include "UtilResourcePool.h" #include "Window.h" #import #import #import #import namespace Rush { struct ShaderMTL : GfxRefCount { u32 uniqueId = 0; id library = nil; id function = nil; static ShaderMTL create(const GfxShaderSource& code); void destroy(); }; struct VertexFormatMTL : GfxRefCount { u32 uniqueId = 0; GfxVertexFormatDesc desc; MTLVertexDescriptor* native = nil; void destroy(); }; struct BufferMTL : GfxRefCount { u32 uniqueId = 0; id native = nil; u32 stride = 0; MTLIndexType indexType = MTLIndexTypeUInt32; void destroy(); }; struct DescriptorSetMTL : GfxRefCount { u32 uniqueId = 0; GfxDescriptorSetDesc desc; DynamicArray constantBufferOffsets; DynamicArray constantBuffers; DynamicArray textures; DynamicArray samplers; DynamicArray storageImages; DynamicArray storageBuffers; id encoder = nil; // #todo: pool argument encoders by descriptor set desc id argBuffer = nil; u32 argBufferOffset = 0; // #todo: pool and sub-allocate arg buffers u32 argBufferSize = 0; void destroy(); }; struct TechniqueMTL : GfxRefCount { u32 uniqueId = 0; GfxTechniqueDesc desc; GfxRef vf; GfxRef vs; GfxRef ps; id computePipeline = nil; u32 constantBufferOffset = 0; u32 samplerOffset = 0; u32 sampledImageOffset = 0; u32 storageImageOffset = 0; u32 storageBufferOffset = 0; u32 descriptorSetCount = 0; Tuple3 workGroupSize = {}; DescriptorSetMTL defaultDescriptorSet; void destroy(); }; struct DepthStencilStateMTL : GfxRefCount { u32 uniqueId = 0; id native = nil; void destroy(); }; struct RasterizerStateMTL : GfxRefCount { u32 uniqueId = 0; GfxRasterizerDesc desc; void destroy(); }; struct TextureMTL : GfxRefCount { u32 uniqueId = 0; id native = nil; GfxTextureDesc desc; static TextureMTL create(const GfxTextureDesc& desc, const GfxTextureData* data, u32 count, const void* pixels); void destroy(); }; struct BlendStateMTL : GfxRefCount { u32 uniqueId = 0; GfxBlendStateDesc desc; void destroy(); }; struct SamplerMTL : GfxRefCount { u32 uniqueId = 0; id native = nil; void destroy(); }; class GfxDevice : public GfxRefCount { public: GfxDevice(Window* window, const GfxConfig& cfg); ~GfxDevice(); u32 generateId(); void beginFrame(); void createDefaultDepthBuffer(u32 width, u32 height); id m_metalDevice = nil; id m_commandQueue = nil; CAMetalLayer* m_metalLayer = nil; ResourcePool m_vertexShaders; ResourcePool m_pixelShaders; ResourcePool m_computeShaders; ResourcePool m_vertexFormats; ResourcePool m_buffers; ResourcePool m_techniques; ResourcePool m_depthStencilStates; ResourcePool m_rasterizerStates; ResourcePool m_textures; ResourcePool m_blendStates; ResourcePool m_samplers; ResourcePool m_descriptorSets; template static GfxOwn makeOwn(HandleType h) { return GfxOwn(h); } Window* m_window = nullptr; WindowEventListener m_resizeEvents; GfxCapability m_caps; GfxStats m_stats; u32 m_uniqueResourceCounter = 1; id m_drawable = nil; id m_backBufferTexture = nil; MTLPixelFormat m_backBufferPixelFormat = MTLPixelFormatInvalid; id m_commandBuffer = nil; GfxRef m_defaultDepthBuffer; }; class GfxContext : public GfxRefCount { public: enum { MaxSampledImages = 16, MaxStorageImages = 8, MaxVertexStreams = 8, MaxConstantBuffers = 4, MaxStorageBuffers = 4, MaxSamplers = 4, MaxDescriptorSets = 4, }; GfxContext(); ~GfxContext(); void applyState(); enum DirtyStateFlag { DirtyStateFlag_Technique = 1 << 0, DirtyStateFlag_PrimitiveType = 1 << 1, DirtyStateFlag_VertexBuffer = 1 << 2, DirtyStateFlag_IndexBuffer = 1 << 3, DirtyStateFlag_Texture = 1 << 4, DirtyStateFlag_BlendState = 1 << 5, DirtyStateFlag_DepthStencilState = 1 << 6, DirtyStateFlag_RasterizerState = 1 << 7, DirtyStateFlag_Sampler = 1 << 8, DirtyStateFlag_ConstantBuffer = 1 << 9, DirtyStateFlag_StorageImage = 1 << 10, DirtyStateFlag_StorageBuffer = 1 << 11, DirtyStateFlag_DescriptorSet = 1 << 12, DirtyStateFlag_Descriptors = DirtyStateFlag_ConstantBuffer | DirtyStateFlag_Texture | DirtyStateFlag_Sampler | DirtyStateFlag_StorageImage | DirtyStateFlag_StorageBuffer, DirtyStateFlag_Pipeline = DirtyStateFlag_Technique | DirtyStateFlag_PrimitiveType | DirtyStateFlag_BlendState | DirtyStateFlag_DepthStencilState | DirtyStateFlag_RasterizerState, }; u32 m_dirtyState = 0xFFFFFFFF; id m_commandEncoder = nil; id m_computeCommandEncoder = nil; id m_depthStencilState = nil; GfxRef m_pendingTechnique; GfxRef m_pendingBlendState; GfxRef m_pendingRasterizerState; GfxRef m_pendingDepthStencilState; GfxRef m_constantBuffers[MaxConstantBuffers]; u32 m_constantBufferOffsets[MaxConstantBuffers] = {}; GfxRef m_samplers[MaxSamplers]; GfxRef m_sampledImages[MaxSampledImages]; GfxRef m_storageImages[MaxStorageImages]; GfxRef m_storageBuffers[MaxStorageBuffers]; GfxRef m_descriptorSets[MaxDescriptorSets]; GfxPassDesc m_passDesc; MTLIndexType m_indexType = MTLIndexTypeUInt32; u32 m_indexStride = 4; id m_indexBuffer = nil; MTLPrimitiveType m_primitiveType = MTLPrimitiveTypeTriangle; MTLPrimitiveTopologyClass m_primitiveTopology = MTLPrimitiveTopologyClassUnspecified; }; } #endif