Exemple #1
0
        public bool Init(AbstractionDesc desc)
        {
            for (int i = 0; i != devices.Length; ++i)
            {
                if (instance is D3D12.Instance)
                {
                    var deviceD3D12 = (D3D12.Device)devices[i];
                    if (!deviceD3D12.Init(desc.deviceDescD3D12))
                    {
                        return(false);
                    }
                }
                else if (instance is Vulkan.Instance)
                {
                    var deviceVulkan = (Vulkan.Device)devices[i];
                    if (!deviceVulkan.Init(desc.deviceDescVulkan))
                    {
                        return(false);
                    }
                }
                else
                {
                    throw new NotImplementedException("Failed to create devices based on instance type: " + instance.GetType().ToString());
                }
            }

            return(true);
        }
Exemple #2
0
        /// <summary>
        /// Initializes first API avaliable to the hardware
        /// NOTE: 'desc' may be modified
        /// </summary>
        public static bool InitFirstAvaliable(AbstractionDesc desc, out InstanceBase instance)
        {
            // validate supported APIs is configured
            if (desc.supportedAPIs == null)
            {
                instance = null;
                return(false);
            }

            // try to init each API until we find one supported by this hardware
            foreach (var api in desc.supportedAPIs)
            {
                switch (api)
                {
                //case AbstractionAPI.WindowsGamingInput:
                //{
                //	throw new NotImplementedException();
                //}
                //break;

                case AbstractionAPI.XInput:
                {
                    var instanceXInput = new XInput.Instance(desc.autoConfigureAbstractions);
                    if (instanceXInput.Init())
                    {
                        instance = instanceXInput;
                        return(true);
                    }
                    else
                    {
                        instanceXInput.Dispose();
                    }
                }
                break;

                case AbstractionAPI.DirectInput:
                {
                    if (!LoadNativeLib(Path.Combine(desc.nativeLibPathDirectInput, DirectInput.Instance.lib)))
                    {
                        continue;
                    }
                    var instanceXInput = new DirectInput.Instance(desc.ignoreXInputDevices, desc.autoConfigureAbstractions);
                    if (instanceXInput.Init(IntPtr.Zero, DirectInput.FeatureLevel.Level_1))
                    {
                        instance = instanceXInput;
                        return(true);
                    }
                    else
                    {
                        instanceXInput.Dispose();
                    }
                }
                break;
                }
            }

            instance = null;
            return(false);
        }
        public static bool InitAllAvaliableInstances(AbstractionDesc desc, out List <InstanceBase> instances)
        {
            instances = new List <InstanceBase>();
            if (desc.supportedAPIs == null)
            {
                return(false);
            }

            foreach (var api in desc.supportedAPIs)
            {
                switch (api)
                {
                                        #if WIN32 || WIN32
                case AbstractionAPI.D3D12:
                {
                    if (!LoadNativeLib(Path.Combine(desc.nativeLibPathD3D12, D3D12.Instance.lib)))
                    {
                        continue;
                    }
                    var instanceD3D12 = new D3D12.Instance();
                    if (instanceD3D12.Init(desc.instanceDescD3D12))
                    {
                        instances.Add(instanceD3D12);
                    }
                    else
                    {
                        instanceD3D12.Dispose();
                    }
                }
                break;

                case AbstractionAPI.Vulkan:
                {
                    if (!LoadNativeLib(Path.Combine(desc.nativeLibPathVulkan, Vulkan.Instance.lib)))
                    {
                        continue;
                    }
                    var instanceVulkan = new Vulkan.Instance();
                    if (instanceVulkan.Init(desc.instanceDescVulkan))
                    {
                        instances.Add(instanceVulkan);
                    }
                    else
                    {
                        instanceVulkan.Dispose();
                    }
                }
                break;
                                        #endif
                }
            }

            return(true);
        }
Exemple #4
0
        public void Init(string platformPath, string folder64Bit, string folder32Bit)
        {
            // pre-load native libs
            string libFolderBit;

            if (IntPtr.Size == 8)
            {
                libFolderBit = folder64Bit;
            }
            else if (IntPtr.Size == 4)
            {
                libFolderBit = folder32Bit;
            }
            else
            {
                throw new NotSupportedException("Unsupported bit size: " + IntPtr.Size.ToString());
            }

                        #if RELEASE
            const string config = "Release";
                        #else
            const string config = "Debug";
                        #endif

            // load api abstraction (api-instance and hardware-device)
            var abstractionDesc = new AbstractionDesc(AbstractionInitType.SingleAPI);
            abstractionDesc.supportedAPIs = new AbstractionAPI[] { AbstractionAPI.XInput };

                        #if DEBUG
            abstractionDesc.nativeLibPathDirectInput = Path.Combine(platformPath, @"Shared\Orbital.Input.DirectInput.Native\bin", libFolderBit, config);
                        #else
            abstractionDesc.nativeLibPathDirectInput = string.Empty;
                        #endif

            if (!Abstraction.InitFirstAvaliable(abstractionDesc, out instance))
            {
                throw new Exception("Failed to init abstraction");
            }
            instance.DeviceConnectedCallback  += Instance_DeviceConnectedCallback;
            instance.GamepadConnectedCallback += Instance_GamepadConnectedCallback;

            if (instance is Orbital.Input.XInput.Instance)
            {
                var instanceXI = (Orbital.Input.XInput.Instance)instance;
                Console.WriteLine("Version: " + instanceXI.version.ToString());
            }

            if (instance is Orbital.Input.DirectInput.Instance)
            {
                var instanceDI = (Orbital.Input.DirectInput.Instance)instance;
                Console.WriteLine("FeatureLevel: " + instanceDI.featureLevel.ToString());
            }
        }
Exemple #5
0
        public void Init(string platformPath, string folder64Bit, string folder32Bit)
        {
            // pre-load native libs
            string libFolderBit;

            if (IntPtr.Size == 8)
            {
                libFolderBit = folder64Bit;
            }
            else if (IntPtr.Size == 4)
            {
                libFolderBit = folder32Bit;
            }
            else
            {
                throw new NotSupportedException("Unsupported bit size: " + IntPtr.Size.ToString());
            }

                        #if RELEASE
            const string config = "Release";
                        #else
            const string config = "Debug";
                        #endif

            // load api abstraction (api-instance and hardware-device)
            var abstractionDesc = new AbstractionDesc(true);
            abstractionDesc.supportedAPIs = new AbstractionAPI[] { AbstractionAPI.D3D12 };

            abstractionDesc.deviceDescD3D12.window = window;
            abstractionDesc.nativeLibPathD3D12     = Path.Combine(platformPath, @"Shared\Orbital.Video.D3D12.Native\bin", libFolderBit, config);

            abstractionDesc.deviceDescVulkan.window = window;
            abstractionDesc.nativeLibPathVulkan     = Path.Combine(platformPath, @"Shared\Orbital.Video.Vulkan.Native\bin", libFolderBit, config);

            if (!Abstraction.InitFirstAvaliable(abstractionDesc, out instance, out device))
            {
                throw new Exception("Failed to init abstraction");
            }

            // create command list
            commandList = device.CreateCommandList();

            // create render pass
            var renderPassDesc = new RenderPassDesc()
            {
                clearColor      = true,
                clearColorValue = new Vec4(0, .2f, .4f, 1)
            };
            renderPass = device.CreateRenderPass(renderPassDesc);

            // create texture
            int textureWidth = 256, textureHeight = 256;
            var textureData = new byte[textureWidth * textureHeight * 4];
            for (int y = 0; y != textureHeight; ++y)
            {
                for (int x = 0; x != textureWidth; ++x)
                {
                    int i = (x * 4) + (y * textureWidth * 4);
                    if (x % 16 <= 7 && y % 16 <= 7)
                    {
                        textureData[i + 0] = 0;
                        textureData[i + 1] = 0;
                        textureData[i + 2] = 0;
                        textureData[i + 3] = 0;
                    }
                    else
                    {
                        textureData[i + 0] = 255;
                        textureData[i + 1] = 255;
                        textureData[i + 2] = 255;
                        textureData[i + 3] = 255;
                    }
                }
            }
            texture = device.CreateTexture2D(TextureFormat.B8G8R8A8, textureWidth, textureHeight, textureData, TextureMode.GPUOptimized);

            // create texture 2
            textureWidth  = 100;
            textureHeight = 100;
            textureData   = new byte[textureWidth * textureHeight * 4];
            for (int y = 0; y != textureHeight; ++y)
            {
                for (int x = 0; x != textureWidth; ++x)
                {
                    int i = (x * 4) + (y * textureWidth * 4);
                    if (x % 16 <= 7 && y % 16 <= 7)
                    {
                        textureData[i + 0] = 0;
                        textureData[i + 1] = 0;
                        textureData[i + 2] = 0;
                        textureData[i + 3] = 0;
                    }
                    else
                    {
                        textureData[i + 0] = 255;
                        textureData[i + 1] = 255;
                        textureData[i + 2] = 255;
                        textureData[i + 3] = 255;
                    }
                }
            }
            texture2 = device.CreateTexture2D(TextureFormat.B8G8R8A8, textureWidth, textureHeight, textureData, TextureMode.GPUOptimized);

            // create constant buffer
            constantBufferObject = new ConstantBufferObject()
            {
                offset    = .5f,
                constrast = .5f
            };
            constantBuffer = device.CreateConstantBuffer <ConstantBufferObject>(constantBufferObject, ConstantBufferMode.Write);

            // load shaders
            // TODO: load CS2X compiled ShaderEffect

            /*using (var stream = new FileStream("Shader.se", FileMode.Open, FileAccess.Read, FileShare.Read))
             * {
             *      shaderEffect = device.CreateShaderEffect(stream, ShaderEffectSamplerAnisotropy.Default);
             * }*/

            using (var vsStream = new FileStream("Shaders\\Shader_D3D12.vs", FileMode.Open, FileAccess.Read, FileShare.Read))
                using (var psStream = new FileStream("Shaders\\Shader_D3D12.ps", FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    var vs = new Video.D3D12.Shader((Video.D3D12.Device)device, ShaderType.VS);
                    var ps = new Video.D3D12.Shader((Video.D3D12.Device)device, ShaderType.PS);
                    if (!vs.Init(vsStream))
                    {
                        throw new Exception("Failed to init VS shader");
                    }
                    if (!ps.Init(psStream))
                    {
                        throw new Exception("Failed to init PS shader");
                    }
                    var desc = new ShaderEffectDesc();
                    desc.constantBuffers    = new ShaderEffectConstantBuffer[1];
                    desc.constantBuffers[0] = new ShaderEffectConstantBuffer()
                    {
                        registerIndex = 0,
                        usage         = ShaderEffectResourceUsage.VS
                    };
                    desc.textures    = new ShaderEffectTexture[2];
                    desc.textures[0] = new ShaderEffectTexture()
                    {
                        registerIndex = 0,
                        usage         = ShaderEffectResourceUsage.PS
                    };
                    desc.textures[1] = new ShaderEffectTexture()
                    {
                        registerIndex = 1,
                        usage         = ShaderEffectResourceUsage.PS
                    };
                    desc.samplers    = new ShaderEffectSampler[1];
                    desc.samplers[0] = new ShaderEffectSampler()
                    {
                        registerIndex = 0,
                        filter        = ShaderEffectSamplerFilter.Default,
                        anisotropy    = ShaderEffectSamplerAnisotropy.Default,
                        addressU      = ShaderEffectSamplerAddress.Wrap,
                        addressV      = ShaderEffectSamplerAddress.Wrap,
                        addressW      = ShaderEffectSamplerAddress.Wrap
                    };
                    shaderEffect = device.CreateShaderEffect(vs, ps, null, null, null, desc, true);
                }

            // create vertex buffer
            var vertexBufferLayout = new VertexBufferLayout();
            vertexBufferLayout.elements    = new VertexBufferLayoutElement[3];
            vertexBufferLayout.elements[0] = new VertexBufferLayoutElement()
            {
                type        = VertexBufferLayoutElementType.Float3,
                usage       = VertexBufferLayoutElementUsage.Position,
                streamIndex = 0, usageIndex = 0, byteOffset = 0
            };
            vertexBufferLayout.elements[1] = new VertexBufferLayoutElement()
            {
                type        = VertexBufferLayoutElementType.RGBAx8,
                usage       = VertexBufferLayoutElementUsage.Color,
                streamIndex = 0, usageIndex = 0, byteOffset = (sizeof(float) * 3)
            };
            vertexBufferLayout.elements[2] = new VertexBufferLayoutElement()
            {
                type        = VertexBufferLayoutElementType.Float2,
                usage       = VertexBufferLayoutElementUsage.UV,
                streamIndex = 0, usageIndex = 0, byteOffset = (sizeof(float) * 3) + 4
            };

            var vertices = new Vertex[]
            {
                new Vertex(new Vec3(-1, -1, 0), Color4.red, new Vec2(0, 0)),
                new Vertex(new Vec3(0, 1, 0), Color4.green, new Vec2(.5f, 1)),
                new Vertex(new Vec3(1, -1, 0), Color4.blue, new Vec2(1, 0))
            };
            vertexBuffer = device.CreateVertexBuffer <Vertex>(vertices, vertexBufferLayout, VertexBufferMode.GPUOptimized);

            // create render state
            var renderStateDesc = new RenderStateDesc()
            {
                renderPass           = renderPass,
                shaderEffect         = shaderEffect,
                constantBuffers      = new ConstantBufferBase[1],
                textures             = new TextureBase[2],
                vertexBuffer         = vertexBuffer,
                vertexBufferTopology = VertexBufferTopology.Triangle
            };
            renderStateDesc.constantBuffers[0] = constantBuffer;
            renderStateDesc.textures[0]        = texture;
            renderStateDesc.textures[1]        = texture2;
            renderState = device.CreateRenderState(renderStateDesc, 0);

            // print all GPUs this abstraction supports
            if (!instance.QuerySupportedAdapters(false, out var adapters))
            {
                throw new Exception("Failed: QuerySupportedAdapters");
            }
            foreach (var adapter in adapters)
            {
                Debug.WriteLine(adapter.name);
            }
        }
        /// <summary>
        /// Initializes first API avaliable to the hardware
        /// NOTE: 'desc' may be modified
        /// </summary>
        public static bool InitFirstAvaliable(AbstractionDesc desc, out InstanceBase instance, out DeviceBase device)
        {
            // validate supported APIs is configured
            if (desc.supportedAPIs == null)
            {
                instance = null;
                device   = null;
                return(false);
            }

            // try to init each API until we find one supported by this hardware
            foreach (var api in desc.supportedAPIs)
            {
                switch (api)
                {
                                        #if WIN32 || WIN32
                case AbstractionAPI.D3D12:
                {
                    if (!LoadNativeLib(Path.Combine(desc.nativeLibPathD3D12, D3D12.Instance.lib)))
                    {
                        continue;
                    }
                    var instanceD3D12 = new D3D12.Instance();
                    if (instanceD3D12.Init(desc.instanceDescD3D12))
                    {
                        var deviceBase = CreateDevice(desc, instanceD3D12);
                        if (deviceBase is D3D12.Device)
                        {
                            var deviceD3D12 = (D3D12.Device)deviceBase;
                            if (deviceD3D12.Init(desc.deviceDescD3D12))
                            {
                                instance = instanceD3D12;
                                device   = deviceD3D12;
                                return(true);
                            }

                            deviceD3D12.Dispose();
                        }
                        else if (deviceBase is mGPU.Device)
                        {
                            var deviceMGPU = (mGPU.Device)deviceBase;
                            if (deviceMGPU.Init(desc))
                            {
                                instance = instanceD3D12;
                                device   = deviceMGPU;
                                return(true);
                            }

                            deviceMGPU.Dispose();
                        }

                        instanceD3D12.Dispose();
                    }
                    else
                    {
                        instanceD3D12.Dispose();
                    }
                }
                break;

                    /*case AbstractionAPI.Vulkan:
                     * {
                     *      if (!LoadNativeLib(Path.Combine(desc.nativeLibPathVulkan, "vulkan-1.dll"))) continue;
                     *      if (!LoadNativeLib(Path.Combine(desc.nativeLibPathVulkan, Vulkan.Instance.lib))) continue;
                     *      var instanceVulkan = new Vulkan.Instance();
                     *      if (instanceVulkan.Init(desc.instanceDescVulkan))
                     *      {
                     *              var deviceVulkan = new Vulkan.Device(instanceVulkan, desc.deviceType);
                     *              if (deviceVulkan.Init(desc.deviceDescVulkan))
                     *              {
                     *                      instance = instanceVulkan;
                     *                      device = deviceVulkan;
                     *                      return true;
                     *              }
                     *
                     *              deviceVulkan.Dispose();
                     *              instanceVulkan.Dispose();
                     *      }
                     *      else
                     *      {
                     *              instanceVulkan.Dispose();
                     *      }
                     * }
                     * break;*/
                                        #endif
                }
            }

            instance = null;
            device   = null;
            return(false);
        }
        private static DeviceBase CreateDevice(AbstractionDesc desc, InstanceBase instance)
        {
            DeviceBase device = null;

            AdapterInfo[] adapters           = null;
            bool          createSingleDevice = false;
            var           initType           = desc.type;

            if (initType == AbstractionInitType.SingleGPU_Standard)
            {
                initType           = AbstractionInitType.SingleGPU_Standard;
                createSingleDevice = true;                // single gpu mode only
            }
            else if (initType == AbstractionInitType.MultiGPU_BestAvaliable_AFR)
            {
                if (!instance.QuerySupportedAdapters(false, out adapters))
                {
                    throw new Exception("Failed to get supported adapters");
                }
                if (adapters.Length >= 1)
                {
                    // test for linked-gpus
                    foreach (var adapter in adapters)
                    {
                        if (adapter.isPrimary && adapter.nodeCount > 1)
                        {
                            initType = AbstractionInitType.MultiGPU_LinkedNode_AFR;
                            break;
                        }
                    }

                    // test for mixed-gpu support
                    if (initType == AbstractionInitType.MultiGPU_BestAvaliable_AFR)
                    {
                        if (adapters.Length >= 2)
                        {
                            foreach (var adapter in adapters)
                            {
                                if (adapter.isPrimary)
                                {
                                    initType = AbstractionInitType.MultiGPU_MixedDevice_AFR;
                                    break;
                                }
                            }
                        }
                    }
                }

                // set to single gpu if no mGPU support found
                if (initType == AbstractionInitType.MultiGPU_BestAvaliable_AFR)
                {
                    initType           = AbstractionInitType.SingleGPU_Standard;
                    createSingleDevice = true;
                }
            }

            if (initType == AbstractionInitType.MultiGPU_LinkedNode_AFR)
            {
                if (adapters == null && !instance.QuerySupportedAdapters(false, out adapters))
                {
                    throw new Exception("Failed to get supported adapters");
                }
                bool linkedNodesFound = false;
                foreach (var adapter in adapters)
                {
                    if (adapter.isPrimary && adapter.nodeCount > 1)
                    {
                        linkedNodesFound = true;
                        break;
                    }
                }

                if (!linkedNodesFound)
                {
                    initType = AbstractionInitType.SingleGPU_Standard; // default to single gpu mode if only adapter-node found
                }
                createSingleDevice = true;                             // always create a single device
            }
            else if (initType == AbstractionInitType.MultiGPU_MixedDevice_AFR)
            {
                if (adapters == null && !instance.QuerySupportedAdapters(false, out adapters))
                {
                    throw new Exception("Failed to get supported adapters");
                }
                if (adapters.Length > 1)
                {
                    // gather all supported adapters
                    List <AdapterInfo> supportedAdapters;
                    if (desc.vendorIgnores_MixedDevices != null)
                    {
                        supportedAdapters = new List <AdapterInfo>();
                        foreach (var adapter in adapters)
                        {
                            if (!IsVendorIgnored(adapter.vendor, desc.vendorIgnores_MixedDevices))
                            {
                                supportedAdapters.Add(adapter);
                            }
                        }
                    }
                    else
                    {
                        supportedAdapters = new List <AdapterInfo>(adapters);
                    }

                    if (supportedAdapters.Count > 1)
                    {
                        device = new mGPU.Device(instance, desc.deviceType, supportedAdapters.ToArray());
                    }
                    else
                    {
                        initType           = AbstractionInitType.SingleGPU_Standard;              // default to single gpu mode if only adapter found
                        createSingleDevice = true;
                    }
                }
                else
                {
                    initType           = AbstractionInitType.SingleGPU_Standard;          // default to single gpu mode if only adapter found
                    createSingleDevice = true;
                }
            }

            // force mixed-device AFR requirements
            if (initType == AbstractionInitType.MultiGPU_MixedDevice_AFR)
            {
                desc.deviceDescD3D12.swapChainType  = SwapChainType.SingleGPU_Standard;
                desc.deviceDescVulkan.swapChainType = SwapChainType.SingleGPU_Standard;
            }

            // create single device if needed
            if (createSingleDevice)
            {
                if (instance is D3D12.Instance)
                {
                    device = new D3D12.Device((D3D12.Instance)instance, desc.deviceType);
                }
                else if (instance is Vulkan.Instance)
                {
                    device = new Vulkan.Device((Vulkan.Instance)instance, desc.deviceType);
                }
            }

            return(device);
        }
        public void Init(string platformPath, string folder64Bit, string folder32Bit)
        {
            // pre-load native libs
            string libFolderBit;

            if (IntPtr.Size == 8)
            {
                libFolderBit = folder64Bit;
            }
            else if (IntPtr.Size == 4)
            {
                libFolderBit = folder32Bit;
            }
            else
            {
                throw new NotSupportedException("Unsupported bit size: " + IntPtr.Size.ToString());
            }

                        #if RELEASE
            const string config = "Release";
                        #else
            const string config = "Debug";
                        #endif

            // load api abstraction (api-instance and hardware-device)
            var abstractionDesc = new AbstractionDesc(AbstractionInitType.DefaultSingleGPU);
            abstractionDesc.supportedAPIs = new AbstractionAPI[] { AbstractionAPI.D3D12 };

            abstractionDesc.deviceDescD3D12.window = window;
            //abstractionDesc.deviceDescD3D12.adapterIndex = 1;
            //abstractionDesc.deviceDescD3D12.vSyncMode = SwapChainVSyncMode.VSyncOff;
            abstractionDesc.nativeLibPathD3D12 = Path.Combine(platformPath, @"Shared\Orbital.Video.D3D12.Native\bin", libFolderBit, config);

            abstractionDesc.deviceDescVulkan.window = window;
            abstractionDesc.nativeLibPathVulkan     = Path.Combine(platformPath, @"Shared\Orbital.Video.Vulkan.Native\bin", libFolderBit, config);

            if (!Abstraction.InitFirstAvaliable(abstractionDesc, out instance, out device))
            {
                throw new Exception("Failed to init abstraction");
            }

            // create render texture test objects
            renderTextureTest = new RenderTextureTest(device);

            // create msaa render texture
            if (!device.GetMaxMSAALevel(TextureFormat.Default, out var msaaLevel))
            {
                throw new Exception("Failed to get MSAA level");
            }
            msaaLevel = MSAALevel.Disabled;
            var windowSize = window.GetSize(WindowSizeType.WorkingArea);
            renderTextureMSAA = device.CreateRenderTexture2D(windowSize.width, windowSize.height, TextureFormat.Default, RenderTextureUsage.Discard, TextureMode.GPUOptimized, StencilUsage.Discard, DepthStencilFormat.DefaultDepth, DepthStencilMode.GPUOptimized, msaaLevel, false, MultiGPUNodeResourceVisibility.All);

            // create command list
            commandList         = device.CreateRasterizeCommandList();
            commandList_Compute = device.CreateComputeCommandList();

            // create render pass
            var renderPassDesc = RenderPassDesc.CreateDefault(new Color4F(0, .2f, .4f, 1), 1);
            //renderPass = device.CreateRenderPass(renderPassDesc, device.swapChain.depthStencil);
            renderPass = renderTextureMSAA.CreateRenderPass(renderPassDesc, renderTextureMSAA.GetDepthStencil());

            // create texture
            int textureWidth = 256, textureHeight = 256;
            var textureData = new byte[textureWidth * textureHeight * 4];
            for (int y = 0; y != textureHeight; ++y)
            {
                for (int x = 0; x != textureWidth; ++x)
                {
                    int i = (x * 4) + (y * textureWidth * 4);
                    if (x % 16 <= 7 && y % 16 <= 7)
                    {
                        textureData[i + 0] = 0;
                        textureData[i + 1] = 0;
                        textureData[i + 2] = 0;
                        textureData[i + 3] = 0;
                    }
                    else
                    {
                        textureData[i + 0] = 255;
                        textureData[i + 1] = 255;
                        textureData[i + 2] = 255;
                        textureData[i + 3] = 255;
                    }
                }
            }
            texture = device.CreateTexture2D(textureWidth, textureHeight, TextureFormat.B8G8R8A8, textureData, TextureMode.GPUOptimized, MultiGPUNodeResourceVisibility.Self);

            // create texture 2
            textureWidth  = 100;
            textureHeight = 100;
            textureData   = new byte[textureWidth * textureHeight * 4];
            for (int y = 0; y != textureHeight; ++y)
            {
                for (int x = 0; x != textureWidth; ++x)
                {
                    int i = (x * 4) + (y * textureWidth * 4);
                    if (x % 16 <= 7 && y % 16 <= 7)
                    {
                        textureData[i + 0] = 0;
                        textureData[i + 1] = 0;
                        textureData[i + 2] = 0;
                        textureData[i + 3] = 0;
                    }
                    else
                    {
                        textureData[i + 0] = 255;
                        textureData[i + 1] = 255;
                        textureData[i + 2] = 255;
                        textureData[i + 3] = 255;
                    }
                }
            }
            texture2 = device.CreateTexture2D(textureWidth, textureHeight, TextureFormat.B8G8R8A8, textureData, TextureMode.GPUOptimized, MultiGPUNodeResourceVisibility.Self);

            // load shaders
            // TODO: load CS2X compiled ShaderEffect

            /*using (var stream = new FileStream("Shader.se", FileMode.Open, FileAccess.Read, FileShare.Read))
             * {
             *      shaderEffect = device.CreateShaderEffect(stream, ShaderEffectSamplerAnisotropy.Default);
             * }*/

            using (var vsStream = new FileStream("Shaders\\Shader_D3D12.vs", FileMode.Open, FileAccess.Read, FileShare.Read))
                using (var psStream = new FileStream("Shaders\\Shader_D3D12.ps", FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    var vs = new Video.D3D12.Shader((Video.D3D12.Device)device, ShaderType.VS);
                    var ps = new Video.D3D12.Shader((Video.D3D12.Device)device, ShaderType.PS);
                    if (!vs.Init(vsStream))
                    {
                        throw new Exception("Failed to init VS shader");
                    }
                    if (!ps.Init(psStream))
                    {
                        throw new Exception("Failed to init PS shader");
                    }
                    var desc = new ShaderEffectDesc();
                    desc.constantBuffers    = new ShaderEffectConstantBuffer[1];
                    desc.constantBuffers[0] = new ShaderEffectConstantBuffer()
                    {
                        registerIndex = 0,
                        usage         = ShaderEffectResourceUsage.VS,
                        variables     = new ShaderVariable[2]
                    };
                    desc.constantBuffers[0].variables[0] = new ShaderVariable()
                    {
                        name = "constrast",
                        type = ShaderVariableType.Float
                    };
                    desc.constantBuffers[0].variables[1] = new ShaderVariable()
                    {
                        name = "camera",
                        type = ShaderVariableType.Float4x4
                    };
                    desc.textures    = new ShaderEffectTexture[3];
                    desc.textures[0] = new ShaderEffectTexture()
                    {
                        registerIndex = 0,
                        usage         = ShaderEffectResourceUsage.PS
                    };
                    desc.textures[1] = new ShaderEffectTexture()
                    {
                        registerIndex = 1,
                        usage         = ShaderEffectResourceUsage.PS
                    };
                    desc.textures[2] = new ShaderEffectTexture()
                    {
                        registerIndex = 2,
                        usage         = ShaderEffectResourceUsage.PS
                    };
                    desc.samplers    = new ShaderEffectSampler[1];
                    desc.samplers[0] = new ShaderEffectSampler()
                    {
                        registerIndex = 0,
                        filter        = ShaderSamplerFilter.Default,
                        anisotropy    = ShaderSamplerAnisotropy.Default,
                        addressU      = ShaderSamplerAddress.Wrap,
                        addressV      = ShaderSamplerAddress.Wrap,
                        addressW      = ShaderSamplerAddress.Wrap,
                        usage         = ShaderEffectResourceUsage.PS
                    };
                    shaderEffect = device.CreateShaderEffect(vs, ps, null, null, null, desc, true);
                }

            if (!shaderEffect.FindVariable("constrast", out shaderEffectVar_Constrast))
            {
                throw new Exception("Failed to find shader effect variable");
            }
            if (!shaderEffect.FindVariable("camera", out shaderEffectVar_Camera))
            {
                throw new Exception("Failed to find shader effect variable");
            }

            // create constant buffer
            constantBuffer = device.CreateConstantBuffer(shaderEffect.constantBufferMappings[0].size, ConstantBufferMode.Write);

            // create vertex buffer
            const float size            = 1 / 2f;
            var         rotUpAxisMat    = Mat3.FromEuler(0, MathTools.DegToRad(90), 0);
            var         rotRightAxisMat = Mat3.FromEuler(MathTools.DegToRad(90), 0, 0);
            var         vertices        = new Vertex[4 * 6]; // 4 vertices per face
            var         indices         = new ushort[6 * 6]; // 6 indices per face
            var         colorKey        = new Color4[4]
            {
                Color4.blue,
                Color4.red,
                Color4.white,
                Color4.white
            };
            for (int v = 0, i = 0, r = 0; v < (4 * 4); v += 4, i += 6, ++r)            // caluclate front, right, back, left faces
            {
                vertices[v + 0] = new Vertex(new Vec3(-size, -size, size), colorKey[r], new Vec2(0, 0)).Transform(rotUpAxisMat, r);
                vertices[v + 1] = new Vertex(new Vec3(-size, size, size), colorKey[r], new Vec2(0, 1)).Transform(rotUpAxisMat, r);
                vertices[v + 2] = new Vertex(new Vec3(size, size, size), colorKey[r], new Vec2(1, 1)).Transform(rotUpAxisMat, r);
                vertices[v + 3] = new Vertex(new Vec3(size, -size, size), colorKey[r], new Vec2(1, 0)).Transform(rotUpAxisMat, r);
                indices[i + 0]  = (ushort)(v + 0);
                indices[i + 1]  = (ushort)(v + 1);
                indices[i + 2]  = (ushort)(v + 2);
                indices[i + 3]  = (ushort)(v + 0);
                indices[i + 4]  = (ushort)(v + 2);
                indices[i + 5]  = (ushort)(v + 3);
            }
            colorKey = new Color4[2]
            {
                Color4.green,
                Color4.white
            };
            for (int v = (4 * 4), i = (6 * 4), r = 1; v < (4 * 6); v += 4, i += 6, r = 3)            // caluclate top, bottom faces
            {
                vertices[v + 0] = new Vertex(new Vec3(-size, -size, size), colorKey[r / 3], new Vec2(0, 0)).Transform(rotRightAxisMat, r);
                vertices[v + 1] = new Vertex(new Vec3(-size, size, size), colorKey[r / 3], new Vec2(0, 1)).Transform(rotRightAxisMat, r);
                vertices[v + 2] = new Vertex(new Vec3(size, size, size), colorKey[r / 3], new Vec2(1, 1)).Transform(rotRightAxisMat, r);
                vertices[v + 3] = new Vertex(new Vec3(size, -size, size), colorKey[r / 3], new Vec2(1, 0)).Transform(rotRightAxisMat, r);
                indices[i + 0]  = (ushort)(v + 0);
                indices[i + 1]  = (ushort)(v + 1);
                indices[i + 2]  = (ushort)(v + 2);
                indices[i + 3]  = (ushort)(v + 0);
                indices[i + 4]  = (ushort)(v + 2);
                indices[i + 5]  = (ushort)(v + 3);
            }
            vertexBuffer = device.CreateVertexBuffer <Vertex>(vertices, indices, VertexBufferMode.GPUOptimized);

            // create vertex buffer streamer
            var vertexBufferStreamLayout = new VertexBufferStreamLayout()
            {
                descs    = new VertexBufferStreamDesc[1],
                elements = new VertexBufferStreamElement[3]
            };
            vertexBufferStreamLayout.descs[0] = new VertexBufferStreamDesc()
            {
                vertexBuffer = vertexBuffer,
                type         = VertexBufferStreamType.VertexData
            };
            vertexBufferStreamLayout.elements[0] = new VertexBufferStreamElement()
            {
                type   = VertexBufferStreamElementType.Float3,
                usage  = VertexBufferStreamElementUsage.Position,
                offset = 0
            };
            vertexBufferStreamLayout.elements[1] = new VertexBufferStreamElement()
            {
                type   = VertexBufferStreamElementType.RGBAx8,
                usage  = VertexBufferStreamElementUsage.Color,
                offset = (sizeof(float) * 3)
            };
            vertexBufferStreamLayout.elements[2] = new VertexBufferStreamElement()
            {
                type   = VertexBufferStreamElementType.Float2,
                usage  = VertexBufferStreamElementUsage.UV,
                offset = (sizeof(float) * 3) + 4
            };
            vertexBufferStreamer = device.CreateVertexBufferStreamer(vertexBufferStreamLayout);

            // create render state
            var renderStateDesc = new RenderStateDesc()
            {
                renderPass           = renderPass,
                shaderEffect         = shaderEffect,
                constantBuffers      = new ConstantBufferBase[1],
                textures             = new TextureBase[3],
                vertexBufferTopology = VertexBufferTopology.Triangle,
                vertexBufferStreamer = vertexBufferStreamer,
                triangleCulling      = TriangleCulling.Back,
                triangleFillMode     = TriangleFillMode.Solid,
                depthStencilDesc     = DepthStencilDesc.StandardDepthTesting()
            };
            //renderStateDesc.blendDesc.renderTargetBlendDescs = new RenderTargetBlendDesc[1] {RenderTargetBlendDesc.AlphaBlending()};
            renderStateDesc.constantBuffers[0] = constantBuffer;
            renderStateDesc.textures[0]        = texture;
            renderStateDesc.textures[1]        = texture2;
            renderStateDesc.textures[2]        = renderTextureTest.renderTexture;
            renderState = device.CreateRenderState(renderStateDesc);

            // create compute shader
            using (var csStream = new FileStream("Shaders\\Compute_D3D12.cs", FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                var csDesc = new ComputeShaderDesc()
                {
                    randomAccessBuffers = new ComputeShaderRandomAccessBuffer[1]
                };
                csDesc.randomAccessBuffers[0] = new ComputeShaderRandomAccessBuffer()
                {
                    registerIndex = 0
                };
                computeShader = device.CreateComputeShader(csStream, csDesc);
            }

            // create compute state
            var computeStateDesc = new ComputeStateDesc()
            {
                computeShader       = computeShader,
                randomAccessBuffers = new object[1]
            };
            computeStateDesc.randomAccessBuffers[0] = renderTextureTest.renderTexture;
            computeState = device.CreateComputeState(computeStateDesc);

            // print all GPUs this abstraction supports
            if (!instance.QuerySupportedAdapters(false, out var adapters))
            {
                throw new Exception("Failed: QuerySupportedAdapters");
            }
            foreach (var adapter in adapters)
            {
                Debug.WriteLine(adapter.name);
            }

            // setup camera
            camera = new Camera();
        }