Skip to content

Commit 98d9382

Browse files
garimagubader
authored andcommitted
[SYCL] Add image accessor read with sampler for host device (#597)
- Support added for sampler with NEAREST Filtering Mode. - Check if the results are consistent with the values read by CPU/GPU device using a test case. - Currently, the test case is enabled only for CPU. Seg faults on GPU. - Added a small test case for as() function in vec class. There is no efficient test case in CTS or in lit-tests. Signed-off-by: Garima Gupta <[email protected]>
1 parent d3b6a49 commit 98d9382

File tree

4 files changed

+336
-33
lines changed

4 files changed

+336
-33
lines changed

sycl/include/CL/sycl/detail/image_accessor_util.hpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ getImageOffset(const vec<T, 4> &Coords, id<3> ImgPitch,
9797
// read from based on Addressing Mode for Nearest filter mode.
9898
cl_int4 getPixelCoordNearestFiltMode(cl_float4, addressing_mode, range<3>);
9999

100+
// Check if PixelCoord are out of range for Sampler with clamp adressing mode.
101+
bool isOutOfRange(cl_int4 PixelCoord, addressing_mode SmplAddrMode,
102+
range<3> ImgRange);
103+
104+
// Get Border Color for the image_channel_order, the border color values are
105+
// only used when the sampler has clamp addressing mode.
106+
cl_float4 getBorderColor(image_channel_order ImgChannelOrder);
107+
100108
// Reads data from a pixel at Ptr location, based on the number of Channels in
101109
// Order and returns the data.
102110
// The datatype used to read from the Ptr is based on the T of the
@@ -957,12 +965,18 @@ DataT imageReadSamplerHostImpl(const CoordT &Coords, const sampler &Smpl,
957965
// Get Pixel Coordinates in integers that will be read from in the Image.
958966
PixelCoord =
959967
getPixelCoordNearestFiltMode(FloatCoorduvw, SmplAddrMode, ImgRange);
960-
// TODO: Check Out-of-range coordinates. Need to use Addressing Mode Of
961-
// Sampler to find the appropriate return value. Eg: clamp_to_edge returns
962-
// edge values and clamp returns border color for out-of-range coordinates.
963-
RetData = ReadPixelDataNearestFiltMode<DataT>(
964-
PixelCoord, ImgPitch, ImgChannelType, ImgChannelOrder, BasePtr,
965-
ElementSize);
968+
969+
// Return Border Color for out-of-range coordinates for Sampler with
970+
// addressing_mode::clamp.
971+
972+
if (isOutOfRange(PixelCoord, SmplAddrMode, ImgRange)) {
973+
cl_float4 BorderColor = (getBorderColor(ImgChannelOrder));
974+
RetData = BorderColor.convert<typename TryToGetElementType<DataT>::type>();
975+
} else {
976+
RetData = ReadPixelDataNearestFiltMode<DataT>(
977+
PixelCoord, ImgPitch, ImgChannelType, ImgChannelOrder, BasePtr,
978+
ElementSize);
979+
}
966980
break;
967981
}
968982
case filtering_mode::linear:

sycl/source/detail/image_accessor_util.cpp

Lines changed: 90 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,43 +15,106 @@ namespace detail {
1515

1616
// For Nearest Filtering mode, process cl_float4 Coordinates and return the
1717
// appropriate Pixel Coordinates based on Addressing Mode.
18-
cl_int4 getPixelCoordNearestFiltMode(cl_float4 Coord_uvw,
18+
cl_int4 getPixelCoordNearestFiltMode(cl_float4 Coorduvw,
1919
addressing_mode SmplAddrMode,
2020
range<3> ImgRange) {
21-
cl_float u = Coord_uvw.x();
22-
cl_float v = Coord_uvw.y();
23-
cl_float w = Coord_uvw.z();
24-
25-
cl_int i = 0;
26-
cl_int j = 0;
27-
cl_int k = 0;
28-
cl_int width = ImgRange[0];
29-
cl_int height = ImgRange[1];
30-
cl_int depth = ImgRange[2];
21+
cl_int4 Coordijk(0);
22+
cl_int4 Rangewhd(ImgRange[0], ImgRange[1], ImgRange[2], 0);
3123
switch (SmplAddrMode) {
32-
case addressing_mode::mirrored_repeat:
33-
// TODO: Add the computations.
34-
break;
35-
case addressing_mode::repeat:
36-
// TODO: Add the computations.
37-
break;
24+
case addressing_mode::mirrored_repeat: {
25+
cl_float4 Tempuvw(0);
26+
Tempuvw = 2.0f * cl::sycl::rint(0.5f * Coorduvw);
27+
Tempuvw = cl::sycl::fabs(Coorduvw - Tempuvw);
28+
Tempuvw = Tempuvw * (Rangewhd.convert<cl_float>());
29+
Tempuvw = (cl::sycl::floor(Tempuvw));
30+
Coordijk = Tempuvw.convert<cl_int>();
31+
Coordijk = cl::sycl::min(Coordijk, (Rangewhd - 1));
32+
// Eg:
33+
// u,v,w = {2.3,1.7,0.5} // normalized coordinates.
34+
// w,h,d = {9,9,9}
35+
// u1=2*rint(1.15)=2
36+
// v1=2*rint(0.85)=2
37+
// w1=2*rint(0.5)=0
38+
// u1=fabs(2.3-2)=.3
39+
// v1=fabs(1.7-2)=.3
40+
// w1=fabs(0.5-0)=.5
41+
// u1=0.3*9=2.7
42+
// v1=0.3*9=2.7
43+
// w1=0.5*9=4.5
44+
// i,j,k = {2,2,4}
45+
46+
} break;
47+
case addressing_mode::repeat: {
48+
49+
cl_float4 Tempuvw(0);
50+
Tempuvw =
51+
(Coorduvw - cl::sycl::floor(Coorduvw)) * Rangewhd.convert<cl_float>();
52+
Coordijk = (cl::sycl::floor(Tempuvw)).convert<cl_int>();
53+
cl_int4 GreaterThanEqual = (Coordijk >= Rangewhd);
54+
Coordijk =
55+
cl::sycl::select(Coordijk, (Coordijk - Rangewhd), GreaterThanEqual);
56+
// Eg:
57+
// u = 2.3; v = 1.5; w = 0.5; // normalized coordinates.
58+
// w,h,d = {9,9,9};
59+
// u1= 0.3*w;
60+
// v1= 0.5*d;
61+
// w1= 0.5*h;
62+
// i = floor(2.7);
63+
// j = floor(4.5);
64+
// k = floor(4.5);
65+
// if (i/j/k > w/h/d-1)
66+
// // Condition is not satisfied.
67+
// (This condition I think will only be satisfied if the floating point
68+
// arithmetic of multiplication
69+
// gave a value in u1/v1/w1 as > w/h/d)
70+
// i = 2; j = 4; k = 4;
71+
} break;
3872
case addressing_mode::clamp_to_edge:
39-
i = cl::sycl::clamp((int)cl::sycl::floor(u), 0, (width - 1));
40-
j = cl::sycl::clamp((int)cl::sycl::floor(v), 0, (height - 1));
41-
k = cl::sycl::clamp((int)cl::sycl::floor(w), 0, (depth - 1));
73+
Coordijk = (cl::sycl::floor(Coorduvw)).convert<cl_int>();
74+
Coordijk = cl::sycl::clamp(Coordijk, cl_int4(0), (Rangewhd - 1));
4275
break;
4376
case addressing_mode::clamp:
44-
i = cl::sycl::clamp((int)cl::sycl::floor(u), -1, width);
45-
j = cl::sycl::clamp((int)cl::sycl::floor(v), -1, height);
46-
k = cl::sycl::clamp((int)cl::sycl::floor(w), -1, depth);
77+
Coordijk = (cl::sycl::floor(Coorduvw)).convert<cl_int>();
78+
Coordijk = cl::sycl::clamp(Coordijk, cl_int4(-1), Rangewhd);
4779
break;
4880
case addressing_mode::none:
49-
i = (int)cl::sycl::floor(u);
50-
j = (int)cl::sycl::floor(v);
51-
k = (int)cl::sycl::floor(w);
81+
Coordijk = (cl::sycl::floor(Coorduvw)).convert<cl_int>();
82+
break;
83+
}
84+
return Coordijk;
85+
}
86+
87+
bool isOutOfRange(const cl_int4 PixelCoord, const addressing_mode SmplAddrMode,
88+
const range<3> ImgRange) {
89+
90+
if (SmplAddrMode != addressing_mode::clamp)
91+
return false;
92+
93+
auto CheckOutOfRange = [](cl_int Coord, cl_int Range) {
94+
return ((Coord < 0) || (Coord >= Range));
95+
};
96+
97+
bool CheckWidth = CheckOutOfRange(PixelCoord.x(),ImgRange[0]);
98+
bool CheckHeight = CheckOutOfRange(PixelCoord.y(),ImgRange[1]);
99+
bool CheckDepth = CheckOutOfRange(PixelCoord.z(),ImgRange[2]);
100+
101+
return (CheckWidth || CheckHeight || CheckDepth);
102+
}
103+
104+
cl_float4 getBorderColor(image_channel_order ImgChannelOrder) {
105+
106+
cl_float4 BorderColor(0.0f);
107+
switch (ImgChannelOrder) {
108+
case image_channel_order::r:
109+
case image_channel_order::rg:
110+
case image_channel_order::rgb:
111+
case image_channel_order::luminance:
112+
BorderColor.w() = 1.0f;
113+
break;
114+
default:
52115
break;
53116
}
54-
return cl_int4{i, j, k, 0};
117+
return BorderColor;
55118
}
56119

57120
} // namespace detail
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
// RUN: %clangxx -fsycl %s -o %t.out
2+
// RUN: env SYCL_DEVICE_TYPE=HOST %t.out
3+
// RUN: %CPU_RUN_PLACEHOLDER %t.out
4+
// RUN: %GPU_RUN_PLACEHOLDER %t.out
5+
// RUN: %ACC_RUN_PLACEHOLDER %t.out
6+
//==------------------- image_accessor_readsampler.cpp ---------------------==//
7+
//==-----------------image_accessor read API test with sampler--------------==//
8+
//
9+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
10+
// See https://llvm.org/LICENSE.txt for license information.
11+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#include <CL/sycl.hpp>
16+
17+
#include <cassert>
18+
#include <iomanip>
19+
#include <iostream>
20+
21+
namespace s = cl::sycl;
22+
23+
template <int unique_number> class kernel_class;
24+
25+
void validateReadData(s::cl_float4 ReadData, s::cl_float4 ExpectedColor) {
26+
// Maximum difference of 1.5 ULP is allowed.
27+
s::cl_int4 PixelDataInt = ReadData.template as<s::cl_int4>();
28+
s::cl_int4 ExpectedDataInt = ExpectedColor.template as<s::cl_int4>();
29+
s::cl_int4 Diff = ExpectedDataInt - PixelDataInt;
30+
#if DEBUG_OUTPUT
31+
{
32+
if (((s::cl_int)Diff.x() <= 1 && (s::cl_int)Diff.x() >= -1) &&
33+
((s::cl_int)Diff.y() <= 1 && (s::cl_int)Diff.y() >= -1) &&
34+
((s::cl_int)Diff.z() <= 1 && (s::cl_int)Diff.z() >= -1) &&
35+
((s::cl_int)Diff.w() <= 1 && (s::cl_int)Diff.w() >= -1)) {
36+
std::cout << "Read Data is correct within precision: " << std::endl;
37+
} else {
38+
std::cout << "Read Data is WRONG/ outside precision: " << std::endl;
39+
}
40+
std::cout << "ReadData: \t"
41+
<< std::setprecision(std::numeric_limits<long double>::digits10 +
42+
1)
43+
<< (float)ReadData.x() * 127 << " " << (float)ReadData.y() * 127
44+
<< " " << (float)ReadData.z() * 127 << " "
45+
<< (float)ReadData.w() * 127 << std::endl;
46+
47+
std::cout << "ExpectedColor: \t" << (float)ExpectedColor.x() * 127 << " "
48+
<< (float)ExpectedColor.y() * 127 << " "
49+
<< (float)ExpectedColor.z() * 127 << " "
50+
<< (float)ExpectedColor.w() * 127 << std::endl;
51+
}
52+
#else
53+
{
54+
assert((s::cl_int)Diff.x() <= 1 && (s::cl_int)Diff.x() >= -1);
55+
assert((s::cl_int)Diff.y() <= 1 && (s::cl_int)Diff.y() >= -1);
56+
assert((s::cl_int)Diff.z() <= 1 && (s::cl_int)Diff.z() >= -1);
57+
assert((s::cl_int)Diff.w() <= 1 && (s::cl_int)Diff.w() >= -1);
58+
}
59+
#endif
60+
}
61+
62+
template <int i>
63+
void checkReadSampler(char *host_ptr, s::sampler Sampler, s::cl_float4 Coord,
64+
s::cl_float4 ExpectedColor) {
65+
66+
s::cl_float4 ReadData;
67+
{
68+
// image with dim = 3
69+
s::image<3> Img(host_ptr, s::image_channel_order::rgba,
70+
s::image_channel_type::snorm_int8, s::range<3>{2, 3, 4});
71+
s::queue myQueue;
72+
s::buffer<s::cl_float4, 1> ReadDataBuf(&ReadData, s::range<1>(1));
73+
myQueue.submit([&](s::handler &cgh) {
74+
auto ReadAcc = Img.get_access<s::cl_float4, s::access::mode::read>(cgh);
75+
s::accessor<s::cl_float4, 1, s::access::mode::write> ReadDataBufAcc(
76+
ReadDataBuf, cgh);
77+
78+
cgh.single_task<class kernel_class<i>>([=](){
79+
s::cl_float4 RetColor = ReadAcc.read(Coord, Sampler);
80+
ReadDataBufAcc[0] = RetColor;
81+
});
82+
});
83+
}
84+
validateReadData(ReadData, ExpectedColor);
85+
}
86+
87+
void checkSamplerNearest() {
88+
89+
// create image:
90+
char host_ptr[100];
91+
for (int i = 0; i < 100; i++)
92+
host_ptr[i] = i;
93+
94+
// Calling only valid configurations.
95+
// A. coordinate normalization mode::normalized
96+
// addressing_mode::mirrored_repeat
97+
{
98+
s::cl_float4 Coord(0.0f, 1.5f, 2.5f,
99+
0.0f); // Out-of-range mirrored_repeat mode
100+
auto Sampler = s::sampler(s::coordinate_normalization_mode::normalized,
101+
s::addressing_mode::mirrored_repeat,
102+
s::filtering_mode::nearest);
103+
checkReadSampler<1>(host_ptr, Sampler, Coord,
104+
s::cl_float4((56.0f / 127.0f), (57.0f / 127.0f),
105+
(58.0f / 127.0f),
106+
(59.0f / 127.0f)) /*Expected Value*/);
107+
}
108+
109+
// addressing_mode::repeat
110+
{
111+
s::cl_float4 Coord(0.0f, 1.5f, 2.5f, 0.0f); // Out-of-range repeat mode
112+
auto Sampler =
113+
s::sampler(s::coordinate_normalization_mode::normalized,
114+
s::addressing_mode::repeat, s::filtering_mode::nearest);
115+
checkReadSampler<2>(host_ptr, Sampler, Coord,
116+
s::cl_float4((56.0f / 127.0f), (57.0f / 127.0f),
117+
(58.0f / 127.0f),
118+
(59.0f / 127.0f)) /*Expected Value*/);
119+
}
120+
121+
// addressing_mode::clamp_to_edge
122+
{
123+
s::cl_float4 Coord(0.0f, 1.5f, 2.5f, 0.0f); // Out-of-range Edge Color
124+
auto Sampler = s::sampler(s::coordinate_normalization_mode::normalized,
125+
s::addressing_mode::clamp_to_edge,
126+
s::filtering_mode::nearest);
127+
checkReadSampler<3>(host_ptr, Sampler, Coord,
128+
s::cl_float4((88.0f / 127.0f), (89.0f / 127.0f),
129+
(90.0f / 127.0f),
130+
(91.0f / 127.0f)) /*Expected Value*/);
131+
}
132+
133+
// addressing_mode::clamp
134+
{
135+
s::cl_float4 Coord(0.0f, 1.5f, 2.5f, 0.0f); // Out-of-range Border Color
136+
auto Sampler =
137+
s::sampler(s::coordinate_normalization_mode::normalized,
138+
s::addressing_mode::clamp, s::filtering_mode::nearest);
139+
checkReadSampler<4>(
140+
host_ptr, Sampler, Coord,
141+
s::cl_float4(0.0f, 0.0f, 0.0f, 0.0f) /*Expected Value*/);
142+
}
143+
144+
// addressing_mode::none
145+
{
146+
s::cl_float4 Coord(0.0f, 0.5f, 0.75f,
147+
0.0f); // In-range for consistent return value.
148+
auto Sampler =
149+
s::sampler(s::coordinate_normalization_mode::normalized,
150+
s::addressing_mode::none, s::filtering_mode::nearest);
151+
checkReadSampler<5>(host_ptr, Sampler, Coord,
152+
s::cl_float4((80.0f / 127.0f), (81.0f / 127.0f),
153+
(82.0f / 127.0f),
154+
(83.0f / 127.0f)) /*Expected Value*/);
155+
}
156+
157+
// B. coordinate_normalization_mode::unnormalized
158+
// addressing_mode::clamp_to_edge
159+
{
160+
s::cl_float4 Coord(0.0f, 1.5f, 2.5f, 0.0f);
161+
auto Sampler = s::sampler(s::coordinate_normalization_mode::unnormalized,
162+
s::addressing_mode::clamp_to_edge,
163+
s::filtering_mode::nearest);
164+
checkReadSampler<6>(host_ptr, Sampler, Coord,
165+
s::cl_float4((56.0f / 127.0f), (57.0f / 127.0f),
166+
(58.0f / 127.0f),
167+
(59.0f / 127.0f)) /*Expected Value*/);
168+
}
169+
170+
// addressing_mode::clamp
171+
{
172+
s::cl_float4 Coord(0.0f, 1.5f, 2.5f, 0.0f);
173+
auto Sampler =
174+
s::sampler(s::coordinate_normalization_mode::unnormalized,
175+
s::addressing_mode::clamp, s::filtering_mode::nearest);
176+
checkReadSampler<7>(host_ptr, Sampler, Coord,
177+
s::cl_float4((56.0f / 127.0f), (57.0f / 127.0f),
178+
(58.0f / 127.0f),
179+
(59.0f / 127.0f)) /*Expected Value*/);
180+
}
181+
182+
// addressing_mode::none
183+
{
184+
s::cl_float4 Coord(0.0f, 1.0f, 2.0f,
185+
0.0f); // In-range for consistent return value.
186+
auto Sampler =
187+
s::sampler(s::coordinate_normalization_mode::unnormalized,
188+
s::addressing_mode::none, s::filtering_mode::nearest);
189+
checkReadSampler<8>(host_ptr, Sampler, Coord,
190+
s::cl_float4((56.0f / 127.0f), (57.0f / 127.0f),
191+
(58.0f / 127.0f),
192+
(59.0f / 127.0f)) /*Expected Value*/);
193+
}
194+
}
195+
196+
void checkSamplerLinear(){
197+
// TODO. Implement this code.
198+
};
199+
200+
int main() {
201+
202+
checkSamplerNearest();
203+
// checkSamplerLinear();
204+
}

0 commit comments

Comments
 (0)