1// 2// Copyright 2023 The ANGLE Project Authors. All rights reserved. 3// Use of this source code is governed by a BSD-style license that can be 4// found in the LICENSE file. 5// 6// CopyImageToBuffer.comp: Supports glReadPixels copying from an image to a PBO. 7// 8// In practice, glReadPixels is normally called with the same format for the PBO as the attachment 9// being read, in which case vkCmdCopyImageToBuffer is used. For simplicity, this shader only 10// supports copying to RGBA8 and BGRA8 formats, but support for more formats can be added if ever 11// required. This restriction makes it convenient because each shader invocation would output a 12// separate uint value. 13 14#version 450 core 15 16#extension GL_EXT_samplerless_texture_functions : require 17 18#define MAKE_SRC_RESOURCE(prefix, type) prefix ## type 19 20#if SrcIsFloat 21#define SRC_RESOURCE(type) type 22#define SrcType vec4 23#else 24#error "Not all source formats are accounted for" 25#endif 26 27#if SrcIs2D 28#define SRC_RESOURCE_NAME texture2D 29#elif SrcIs3D 30#define SRC_RESOURCE_NAME texture3D 31#else 32#error "Not all source types are accounted for" 33#endif 34 35layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; 36 37layout(set = 0, binding = 0) uniform SRC_RESOURCE(SRC_RESOURCE_NAME) src; 38 39layout (set = 0, binding = 1) buffer dst 40{ 41 uint destData[]; 42}; 43 44layout (push_constant) uniform PushConstants 45{ 46 // Source image to read from 47 uvec2 srcOffset; 48 int srcDepth; 49 // Whether readback should be done in inverse row order 50 bool reverseRowOrder; 51 52 // Width and height of the copy 53 uvec2 size; 54 // Offset into destData to write to in uints 55 uint outputOffset; 56 // Output pitch in uints (number of uints per row) 57 uint outputPitch; 58 // Whether the output is snorm or unorm 59 bool isDstSnorm; 60} params; 61 62SrcType getSourceValue() 63{ 64 uvec2 coord = gl_GlobalInvocationID.xy; 65 if (params.reverseRowOrder) 66 { 67 coord.y = params.size.y - coord.y - 1; 68 } 69 coord += params.srcOffset; 70 71#if SrcIs2D 72 SrcType srcValue = texelFetch(src, ivec2(coord), 0); 73#elif SrcIs3D 74 SrcType srcValue = texelFetch(src, ivec3(coord, params.srcDepth), 0); 75#else 76#error "Not all source types are accounted for" 77#endif 78 79 return srcValue; 80} 81 82uint convertToDestValue(SrcType srcValue) 83{ 84#if SrcIsFloat 85 uvec4 normalized; 86 if (params.isDstSnorm) 87 { 88 ivec4 scaled = ivec4(srcValue * 127.0); 89 normalized = uvec4(scaled); 90 } 91 else 92 { 93 normalized = uvec4(clamp(srcValue, 0.0, 1.0) * 255.0); 94 } 95 96 normalized &= 0xFF; 97 98 return normalized.r | normalized.g << 8 | normalized.b << 16 | normalized.a << 24; 99#else 100#error "Not all source formats are accounted for" 101#endif 102} 103 104void outputDestValue(uint destValue) 105{ 106 uint offset = params.outputOffset + params.outputPitch * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x; 107 destData[offset] = destValue; 108} 109 110void main() 111{ 112 if (any(greaterThanEqual(gl_GlobalInvocationID.xy, params.size))) 113 return; 114 115 SrcType srcValue = getSourceValue(); 116 uint destValue = convertToDestValue(srcValue); 117 outputDestValue(destValue); 118} 119