• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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