Пример #1
0
        public static ShaderModule LoadShaderModule(IVulkanAppHost host, VulkanContext ctx, string path)
        {
            const int defaultBufferSize = 4096;

            using (Stream stream = host.Open(path))
                using (var ms = new MemoryStream())
                {
                    stream.CopyTo(ms, defaultBufferSize);
                    return(ctx.Device.CreateShaderModule(new ShaderModuleCreateInfo(ms.ToArray())));
                }
        }
Пример #2
0
        public void Initialize(IVulkanAppHost host)
        {
            Host = host;
#if DEBUG
            const bool debug = true;
#else
            const bool debug = false;
#endif
            _initializingPermanent = true;
            // Calling ToDispose here registers the resource to be automatically disposed on exit.
            Instance                   = ToDispose(CreateInstance(debug));
            DebugReportCallback        = ToDispose(CreateDebugReportCallback(debug));
            Surface                    = ToDispose(CreateSurface());
            Context                    = ToDispose(new VulkanContext(Instance, Surface, Host.Platform));
            Content                    = ToDispose(new ContentManager(Host, Context, "Content"));
            ImageAvailableSemaphore    = ToDispose(Context.Device.CreateSemaphore());
            RenderingFinishedSemaphore = ToDispose(Context.Device.CreateSemaphore());

            if (host.Platform == Platform.MacOS)
            {
                //Setup MoltenVK specific device configuration.
                MVKDeviceConfiguration deviceConfig = Context.Device.GetMVKDeviceConfiguration();
                deviceConfig.DebugMode                    = debug;
                deviceConfig.PerformanceTracking          = debug;
                deviceConfig.PerformanceLoggingFrameCount = debug ? 300 : 0;
                Context.Device.SetMVKDeviceConfiguration(deviceConfig);
            }

            _initializingPermanent = false;
            // Calling ToDispose here registers the resource to be automatically disposed on events
            // such as window resize.
            Swapchain = ToDispose(CreateSwapchain());
            // Acquire underlying images of the freshly created swapchain.
            SwapchainImages = Swapchain.GetImages();
            // Create a command buffer for each swapchain image.
            CommandBuffers = Context.GraphicsCommandPool.AllocateBuffers(
                new CommandBufferAllocateInfo(CommandBufferLevel.Primary, SwapchainImages.Length));
            // Create a fence for each commandbuffer so that we can wait before using it again
            _initializingPermanent = true; //We need our fences to be there permanently
            SubmitFences           = new Fence[SwapchainImages.Length];
            for (int i = 0; i < SubmitFences.Length; i++)
            {
                ToDispose(SubmitFences[i] = Context.Device.CreateFence(new FenceCreateInfo(FenceCreateFlags.Signaled)));
            }

            // Allow concrete samples to initialize their resources.
            InitializePermanent();
            _initializingPermanent = false;
            InitializeFrame();

            // Record commands for execution by Vulkan.
            RecordCommandBuffers();
        }
Пример #3
0
        public static VkShaderModule LoadShaderModule(IVulkanAppHost host, VulkanContext ctx, string path)
        {
            const int defaultBufferSize = 4096;

            using (Stream stream = host.Open(path))
                using (var ms = new MemoryStream())
                {
                    stream.CopyTo(ms, defaultBufferSize);

                    byte[] bytes = ms.ToArray();

                    // Create a new shader module that will be used for Pipeline creation
                    VkShaderModule shaderModule;
                    vkCreateShaderModule(ctx.Device, bytes, null, out shaderModule);
                    return(shaderModule);
                }
        }
Пример #4
0
        public void Initialize(IVulkanAppHost host)
        {
            Host = host;
#if DEBUG
            const bool debug = true;
#else
            const bool debug = false;
#endif
            _initializingPermanent = true;
            // Calling ToDispose here registers the resource to be automatically disposed on exit.
            Instance                   = ToDispose(CreateInstance(debug));
            DebugReportCallback        = ToDispose(CreateDebugReportCallback(debug));
            Surface                    = ToDispose(CreateSurface());
            Context                    = ToDispose(new VulkanContext(Instance, Surface, Host.Platform));
            Content                    = ToDispose(new ContentManager(Host, Context, "Content"));
            ImageAvailableSemaphore    = ToDispose(Context.Device.CreateSemaphore());
            RenderingFinishedSemaphore = ToDispose(Context.Device.CreateSemaphore());

            _initializingPermanent = false;
            // Calling ToDispose here registers the resource to be automatically disposed on events
            // such as window resize.
            Swapchain = ToDispose(CreateSwapchain());
            // Acquire underlying images of the freshly created swapchain.
            SwapchainImages = Swapchain.GetImages();
            // Create a command buffer for each swapchain image.
            CommandBuffers = Context.GraphicsCommandPool.AllocateBuffers(
                new CommandBufferAllocateInfo(CommandBufferLevel.Primary, SwapchainImages.Length));

            // Allow concrete samples to initialize their resources.
            _initializingPermanent = true;
            InitializePermanent();
            _initializingPermanent = false;
            InitializeFrame();

            // Record commands for execution by Vulkan.
            RecordCommandBuffers();
        }
Пример #5
0
        public static VulkanImage LoadKtxVulkanImage(IVulkanAppHost host, VulkanContext ctx, string path)
        {
            using (var reader = new BinaryReader(host.Open(path)))
            {
                byte[] identifier = reader.ReadBytes(12);

                if (!identifier.SequenceEqual(KtxIdentifier))
                {
                    throw new InvalidOperationException("File is not in Khronos Texture format.");
                }

                int endienness            = reader.ReadInt32();
                int glType                = reader.ReadInt32();
                int glTypeSize            = reader.ReadInt32();
                int glFormat              = reader.ReadInt32();
                int glInternalFormat      = reader.ReadInt32();
                int glBaseInternalFormat  = reader.ReadInt32();
                int pixelWidth            = reader.ReadInt32();
                int pixelHeight           = reader.ReadInt32();
                int pixelDepth            = reader.ReadInt32();
                int numberOfArrayElements = reader.ReadInt32();
                int numberOfFaces         = reader.ReadInt32();
                int numberOfMipmapLevels  = reader.ReadInt32();
                int bytesOfKeyValueData   = reader.ReadInt32();

                // Skip key-value data.
                reader.ReadBytes(bytesOfKeyValueData);

                // Some of the values may be 0 - ensure at least 1.
                pixelWidth            = Math.Max(pixelWidth, 1);
                pixelHeight           = Math.Max(pixelHeight, 1);
                pixelDepth            = Math.Max(pixelDepth, 1);
                numberOfArrayElements = Math.Max(numberOfArrayElements, 1);
                numberOfFaces         = Math.Max(numberOfFaces, 1);
                numberOfMipmapLevels  = Math.Max(numberOfMipmapLevels, 1);

                int numberOfSlices = Math.Max(numberOfFaces, numberOfArrayElements);

                if (!_glInternalFormatToVkFormat.TryGetValue(glInternalFormat, out Format format))
                {
                    throw new NotImplementedException("glInternalFormat not mapped to VkFormat.");
                }

                var data = new TextureData
                {
                    Mipmaps = new TextureData.Mipmap[numberOfMipmapLevels],
                    Format  = format
                };

                for (int i = 0; i < numberOfMipmapLevels; i++)
                {
                    var mipmap = new TextureData.Mipmap();
                    mipmap.Size     = reader.ReadInt32();
                    mipmap.Extent   = new Extent3D(pixelWidth, pixelHeight, pixelDepth);
                    mipmap.Data     = reader.ReadBytes(mipmap.Size);
                    data.Mipmaps[i] = mipmap;
                    break; // TODO: impl
                    //for (int j = 0; j < numberOfArrayElements; j++)
                    //{
                    //    for (int k = 0; k < numberOfFaces; k++)
                    //    {
                    //        for (int l = 0; l < pixelDepth; l++)
                    //        {
                    //            //for (int row = 0;
                    //            //    row < )
                    //        }
                    //    }
                    //}
                }

                return(VulkanImage.Texture2D(ctx, data));
            }
        }
Пример #6
0
 public ContentManager(IVulkanAppHost host, VulkanContext ctx, string contentRoot)
 {
     _host        = host;
     _ctx         = ctx;
     _contentRoot = contentRoot;
 }
Пример #7
0
        public void Initialize(IVulkanAppHost host)
        {
            Host = host;
#if DEBUG
            const bool debug = true;
#else
            const bool debug = false;
#endif
            _initializingPermanent = true;

            VkResult result = vkInitialize();
            result.CheckResult();

            // Calling ToDispose here registers the resource to be automatically disposed on exit.
            Instance = CreateInstance(debug);
            Surface  = CreateSurface();
            Context  = new VulkanContext(Instance, Surface, Host.Platform);
            Content  = new ContentManager(Host, Context, "Content");
            ImageAvailableSemaphore    = CreateSemaphore(Context.Device);
            RenderingFinishedSemaphore = CreateSemaphore(Context.Device);

            _initializingPermanent = false;
            // Calling ToDispose here registers the resource to be automatically disposed on events
            // such as window resize.
            var swapchain = CreateSwapchain();
            Swapchain = swapchain;
            ToDispose(new ActionDisposable(() =>
            {
                vkDestroySwapchainKHR(Context.Device, swapchain, null);
            }));

            // Acquire underlying images of the freshly created swapchain.
            uint swapchainImageCount;
            result = vkGetSwapchainImagesKHR(Context.Device, Swapchain, &swapchainImageCount, null);
            result.CheckResult();

            var swapchainImages = stackalloc VkImage[(int)swapchainImageCount];
            result = vkGetSwapchainImagesKHR(Context.Device, Swapchain, &swapchainImageCount, swapchainImages);
            result.CheckResult();

            SwapchainImages = new VkImage[swapchainImageCount];
            for (int i = 0; i < swapchainImageCount; i++)
            {
                SwapchainImages[i] = swapchainImages[i];
            }

            VkCommandBufferAllocateInfo allocInfo = new VkCommandBufferAllocateInfo()
            {
                sType       = VkStructureType.CommandBufferAllocateInfo,
                commandPool = Context.GraphicsCommandPool,

                level = VkCommandBufferLevel.Primary,
                commandBufferCount = (uint)SwapchainImages.Length,
            };

            VkCommandBuffer[] commandBuffers = new VkCommandBuffer[SwapchainImages.Length];
            fixed(VkCommandBuffer *commandBuffersPtr = &commandBuffers[0])
            {
                vkAllocateCommandBuffers(Context.Device, &allocInfo, commandBuffersPtr).CheckResult();
            }

            CommandBuffers = commandBuffers;

            // Create a fence for each commandbuffer so that we can wait before using it again
            _initializingPermanent = true; //We need our fences to be there permanently
            SubmitFences           = new VkFence[SwapchainImages.Length];
            for (int i = 0; i < SubmitFences.Length; i++)
            {
                VkFenceCreateInfo fenceCreateInfo = new VkFenceCreateInfo()
                {
                    sType = VkStructureType.FenceCreateInfo,
                    pNext = null,
                    flags = VkFenceCreateFlags.Signaled
                };

                VkFence handle;

                vkCreateFence(Context.Device, &fenceCreateInfo, null, out handle);

                SubmitFences[i] = handle;
                ToDispose(new ActionDisposable(() =>
                {
                    vkDestroyFence(Context.Device, handle, null);
                }));
            }

            // Allow concrete samples to initialize their resources.
            InitializePermanent();
            _initializingPermanent = false;
            InitializeFrame();

            // Record commands for execution by Vulkan.
            RecordCommandBuffers();
        }