internal static DeviceTexture CreateColorTarget(
            Int2 size,
            Format format,
            Device logicalDevice,
            Memory.Pool memoryPool,
            TransientExecutor executor,
            bool allowSampling = true)
        {
            if (logicalDevice == null)
            {
                throw new ArgumentNullException(nameof(logicalDevice));
            }
            if (memoryPool == null)
            {
                throw new ArgumentNullException(nameof(memoryPool));
            }
            if (executor == null)
            {
                throw new ArgumentNullException(nameof(executor));
            }

            var usage = allowSampling
                ? ImageUsages.ColorAttachment | ImageUsages.Sampled
                : ImageUsages.ColorAttachment | ImageUsages.TransientAttachment;
            var aspects = ImageAspects.Color;
            var image   = CreateImage(
                logicalDevice,
                format,
                size,
                mipLevels: 1,
                usage,
                cubeMap: false);
            var memory = memoryPool.AllocateAndBind(image, Chunk.Location.Device);

            //Transition the image to the depth attachment layout
            TransitionImageLayout(image, aspects,
                                  baseMipLevel: 0,
                                  mipLevels: 1,
                                  baseLayer: 0,
                                  layers: 1,
                                  oldLayout: ImageLayout.Undefined,
                                  newLayout: ImageLayout.ColorAttachmentOptimal,
                                  executor: executor);

            var view = CreateView(image, format, mipLevels: 1, aspects, cubeMap: false);

            return(new DeviceTexture(
                       size,
                       format,
                       ImageLayout.ShaderReadOnlyOptimal, //Used for shader reading
                       mipLevels: 1,
                       aspects,
                       image,
                       memory,
                       view));
        }
        internal static DeviceTexture UploadTexture(
            IInternalTexture texture,
            Device logicalDevice,
            Memory.Pool memoryPool,
            Memory.HostBuffer stagingBuffer,
            TransientExecutor executor,
            bool generateMipMaps = false)
        {
            if (texture == null)
            {
                throw new ArgumentNullException(nameof(texture));
            }
            if (logicalDevice == null)
            {
                throw new ArgumentNullException(nameof(logicalDevice));
            }
            if (memoryPool == null)
            {
                throw new ArgumentNullException(nameof(memoryPool));
            }
            if (stagingBuffer == null)
            {
                throw new ArgumentNullException(nameof(stagingBuffer));
            }
            if (executor == null)
            {
                throw new ArgumentNullException(nameof(executor));
            }

            int mipLevels = generateMipMaps ? CalculateMipLevels(texture.Size) : 1;
            int layers    = texture.IsCubeMap ? 6 : 1;
            var aspects   = ImageAspects.Color;
            var image     = CreateImage(
                logicalDevice,
                texture.Format,
                texture.Size,
                mipLevels,
                //Also include 'TransferSrc' because we read from the image to generate the mip-maps
                ImageUsages.TransferSrc | ImageUsages.TransferDst | ImageUsages.Sampled,
                cubeMap: texture.IsCubeMap);
            var memory = memoryPool.AllocateAndBind(image, Chunk.Location.Device);

            //Transition the entire image (all mip-levels and layers) to 'TransferDstOptimal'
            TransitionImageLayout(image, aspects,
                                  baseMipLevel: 0, mipLevels, baseLayer: 0, layers,
                                  oldLayout: ImageLayout.Undefined,
                                  newLayout: ImageLayout.TransferDstOptimal,
                                  executor: executor);

            //Upload the data to mipmap 0
            texture.Upload(stagingBuffer, executor, image, aspects);

            //Create the other mipmap levels
            Int2 prevMipSize = texture.Size;

            for (int i = 1; i < mipLevels; i++)
            {
                Int2 curMipSize = new Int2(
                    prevMipSize.X > 1 ? prevMipSize.X / 2 : 1,
                    prevMipSize.Y > 1 ? prevMipSize.Y / 2 : 1);

                //Move the previous mip-level to a transfer source layout
                TransitionImageLayout(image, aspects,
                                      baseMipLevel: i - 1, mipLevels: 1,
                                      baseLayer: 0, layers,
                                      oldLayout: ImageLayout.TransferDstOptimal,
                                      newLayout: ImageLayout.TransferSrcOptimal,
                                      executor: executor);

                //Blit the previous mip-level to the current at half the size
                BlitImage(aspects,
                          fromImage: image,
                          fromRegion: new IntRect(min: Int2.Zero, max: prevMipSize),
                          fromMipLevel: i - 1,
                          fromLayerCount: layers,
                          toImage: image,
                          toRegion: new IntRect(min: Int2.Zero, max: curMipSize),
                          toMipLevel: i,
                          toLayerCount: layers,
                          executor);

                //Transition the previous mip-level to the shader-read layout
                TransitionImageLayout(image, aspects,
                                      baseMipLevel: i - 1, mipLevels: 1,
                                      baseLayer: 0, layers,
                                      oldLayout: ImageLayout.TransferSrcOptimal,
                                      newLayout: ImageLayout.ShaderReadOnlyOptimal,
                                      executor: executor);

                //Update the prev mip-size
                prevMipSize = curMipSize;
            }

            //Transition the last mip-level to the shader-read layout
            TransitionImageLayout(image, aspects,
                                  baseMipLevel: mipLevels - 1, mipLevels: 1,
                                  baseLayer: 0, layers,
                                  oldLayout: ImageLayout.TransferDstOptimal,
                                  newLayout: ImageLayout.ShaderReadOnlyOptimal,
                                  executor: executor);

            var view = CreateView(
                image, texture.Format, mipLevels, aspects, cubeMap: texture.IsCubeMap);

            return(new DeviceTexture(
                       texture.Size,
                       texture.Format,
                       ImageLayout.ShaderReadOnlyOptimal, //Used for shader reading,
                       mipLevels,
                       aspects,
                       image,
                       memory,
                       view));
        }
Exemple #3
0
        public RenderScene(Window window,
                           TextureInfo reflectionTexture,
                           ShaderProgram postVertProg,
                           ShaderProgram bloomFragProg,
                           ShaderProgram aoFragProg,
                           ShaderProgram gaussBlurFragProg,
                           ShaderProgram boxBlurFragProg,
                           ShaderProgram compositionFragProg,
                           Logger logger = null)
        {
            if (window == null)
            {
                throw new ArgumentNullException(nameof(window));
            }
            if (reflectionTexture.Texture == null)
            {
                throw new ArgumentNullException(nameof(reflectionTexture));
            }
            if (postVertProg == null)
            {
                throw new ArgumentNullException(nameof(postVertProg));
            }
            if (bloomFragProg == null)
            {
                throw new ArgumentNullException(nameof(bloomFragProg));
            }
            if (aoFragProg == null)
            {
                throw new ArgumentNullException(nameof(aoFragProg));
            }
            if (gaussBlurFragProg == null)
            {
                throw new ArgumentNullException(nameof(gaussBlurFragProg));
            }
            if (boxBlurFragProg == null)
            {
                throw new ArgumentNullException(nameof(boxBlurFragProg));
            }
            if (compositionFragProg == null)
            {
                throw new ArgumentNullException(nameof(compositionFragProg));
            }

            this.window = window;
            this.logger = logger;
            camera      = new Camera();

            //Create resources
            executor      = new TransientExecutor(window.LogicalDevice, window.GraphicsFamilyIndex);
            memoryPool    = new Memory.Pool(window.LogicalDevice, window.HostDevice, logger);
            stagingBuffer = new Memory.HostBuffer(
                window.LogicalDevice,
                memoryPool,
                BufferUsages.TransferSrc,
                size: ByteUtils.MegabyteToByte(16));
            sceneDataBuffer = new Memory.HostBuffer(
                window.LogicalDevice, memoryPool, BufferUsages.UniformBuffer,
                size: SceneData.SIZE * window.SwapchainCount);
            inputManager = new ShaderInputManager(window.LogicalDevice, logger);

            //Create techniques
            gbufferTechnique = new GBufferTechnique(this, logger);
            shadowTechnique  = new ShadowTechnique(this, logger);
            bloomTechnique   = new BloomTechnique(
                gbufferTechnique, postVertProg, bloomFragProg, gaussBlurFragProg, this, logger);
            aoTechnique = new AmbientOcclusionTechnique(
                gbufferTechnique, postVertProg, aoFragProg, boxBlurFragProg, this, logger);
            deferredTechnique = new DeferredTechnique(
                gbufferTechnique, shadowTechnique, bloomTechnique, aoTechnique,
                reflectionTexture, postVertProg, compositionFragProg,
                this, logger);
        }