internal CubeTexture( IInternalTexture left, IInternalTexture right, IInternalTexture up, IInternalTexture down, IInternalTexture front, IInternalTexture back) { if (left == null) { throw new ArgumentNullException(nameof(left)); } if (right == null) { throw new ArgumentNullException(nameof(right)); } if (up == null) { throw new ArgumentNullException(nameof(up)); } if (down == null) { throw new ArgumentNullException(nameof(down)); } if (front == null) { throw new ArgumentNullException(nameof(front)); } if (back == null) { throw new ArgumentNullException(nameof(back)); } size = left.Size; if (right.Size != size || up.Size != size || down.Size != size || front.Size != size || back.Size != size) { throw new ArgumentException( $"[{nameof(CubeTexture)}] All faces of the cube-map need to have the same size", nameof(size)); } Format format = left.Format; if (right.Format != format || up.Format != format || down.Format != format || front.Format != format || back.Format != format) { throw new ArgumentException( $"[{nameof(CubeTexture)}] All faces of the cube-map need to have the same format", nameof(size)); } faces = new IInternalTexture[6]; faces[0] = left; faces[1] = right; faces[2] = up; faces[3] = down; faces[4] = front; faces[5] = back; }
internal static DeviceTexture UploadTexture( IInternalTexture texture, RenderScene scene, bool generateMipMaps = false) { return(UploadTexture( texture, scene.LogicalDevice, scene.MemoryPool, scene.StagingBuffer, scene.Executor, generateMipMaps)); }
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)); }