Conversation
bob80905
left a comment
There was a problem hiding this comment.
Is this the complete set of elementwise intrinsics, or are there more to come?
If there's going to be many more to come, I wonder if it would be better to find a way to consolidate and parameterize these tests, they are quite repetitive.
| # RUN: %dxc_target -T %if Clang %{ps_6_0%} %else %{ps_6_9%} -Fo %t-pixel.o %t/pixel.hlsl | ||
| # RUN: %offloader %t/pipeline.yaml %t-vertex.o %t-pixel.o | FileCheck %s | ||
|
|
||
| # CHECK: Name: Output |
There was a problem hiding this comment.
I don't think it is conventional to run filecheck in the offload test suites, and buffer comparisons are preferred. Is there a reason you use filecheck here?
There was a problem hiding this comment.
Yes because the ddy\ddx tests are pixel shader specific so we are not writing to a buffer the way our compute shaders do. I could potentially try and use gold images instead and do image compares via imgdiff. Thats how many of the other ddy\ddx testing has been done, but that is a bit more painful to test locally.
There was a problem hiding this comment.
I thought about this a bit more and my plan to replace these checks with imgdiff did not workout. Long vector usage on an image is hard to wrap my brain around. I think you are right it will just be easier to do buffer comparisons and avoid file check all together.
| # Unimplemented https://github.com/llvm/wg-hlsl/issues/467 | ||
| # XFAIL: Vulkan | ||
|
|
||
| # CI machines don't have SM 6.9 support yet |
There was a problem hiding this comment.
Isn't this only true for metal at the moment?
There was a problem hiding this comment.
These lines don't have to be removed, but can be removed now. essentially if you don't have a new enough agility sdk then this requies allows us to skip the tests. CI has been updated so only value is for folks that don't have latest sdk setup to not get a bunch of test fails. But thats probably not something we want to encourage for users testing their code via this project.
20a1348 to
e05c661
Compare
|
So this is interesting some long vector tests just started passing on vulkan without any changes from us: |
fab8ecb to
8d4aa85
Compare
bogner
left a comment
There was a problem hiding this comment.
Do we need to test multiple sizes of vector for every single intrinsic? I think a single call to each elementwise intrinsic should be sufficient to prove that they work. Having just one of these tests cover the separate 5/8/16 cases seems sufficient to me.
| vector<float, 5> Input0_5; | ||
| for (uint I = 0; I < 5; ++I) | ||
| Input0_5[I] = In0[0 + I]; | ||
| vector<float, 5> Result5 = acos(Input0_5); | ||
| for (uint I = 0; I < 5; ++I) | ||
| Out[0 + I] = Result5[I]; |
There was a problem hiding this comment.
We could save a bit of typing here if we use ByteAddressBuffer rather than StructuredBuffer. Consider:
vector<float, 5> Input0_5 = In0.Load< vector<float, 5> >(0);
vector<float, 5> Result5 = acos(Input0_5);
Out.Store< vector<float, 5> >(0, Result5);or even:
Out.Store< vector<float, 5> >(0, acos(In0.Load< vector<float, 5> >(0)));There was a problem hiding this comment.
I really like your suggestion, however while less code this generates newer DirectX instructions to handle loads and stores
If I do:
ByteAddressBuffer In0 : register(t0);
RWByteAddressBuffer Out : register(u1);
[numthreads(1,1,1)]
void main() {
Out.Store< vector<float, 16> >(0, asfloat(In0.Load< vector<uint, 16> >(0)));
}I generate https://hlsl.godbolt.org/z/hz846Tb4b
define void @main() {
%Out_UAV_rawbuf = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 1, i32 1, i32 0, i8 1 }, i32 1, i1 false), !dbg !32 ; line:6 col:45 ; CreateHandleFromBinding(bind,index,nonUniformIndex)
%In0_texture_rawbuf = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind zeroinitializer, i32 0, i1 false), !dbg !32 ; line:6 col:45 ; CreateHandleFromBinding(bind,index,nonUniformIndex)
%1 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %In0_texture_rawbuf, %dx.types.ResourceProperties { i32 11, i32 0 }), !dbg !32 ; line:6 col:45 ; AnnotateHandle(res,props) resource: ByteAddressBuffer
%RawBufferVectorLoad = call %dx.types.ResRet.v16i32 @dx.op.rawBufferVectorLoad.v16i32(i32 303, %dx.types.Handle %1, i32 0, i32 undef, i32 4), !dbg !32 ; line:6 col:45 ; RawBufferVectorLoad(buf,index,elementOffset,alignment)
%2 = extractvalue %dx.types.ResRet.v16i32 %RawBufferVectorLoad, 0, !dbg !32 ; line:6 col:45
%3 = bitcast <16 x i32> %2 to <16 x float>, !dbg !33 ; line:6 col:37
%4 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %Out_UAV_rawbuf, %dx.types.ResourceProperties { i32 4107, i32 0 }), !dbg !34 ; line:6 col:3 ; AnnotateHandle(res,props) resource: RWByteAddressBuffer
call void @dx.op.rawBufferVectorStore.v16f32(i32 304, %dx.types.Handle %4, i32 0, i32 undef, <16 x float> %3, i32 4), !dbg !34 ; line:6 col:3 ; RawBufferVectorStore(uav,index,elementOffset,value0,alignment)
ret void, !dbg !35 ; line:7 col:1
}The problematic instructions being @dx.op.rawBufferVectorLoad.v16i32 and @dx.op.rawBufferVectorStore.v16f32.
However if I do
StructuredBuffer<uint> In0 : register(t0);
RWStructuredBuffer<float> Out : register(u1);
[numthreads(1,1,1)]
void main() {
vector<uint, 16> Input0_16;
for (uint I = 0; I < 16; ++I)
Input0_16[I] = In0[13 + I];
vector<float, 16> Result16 = asfloat(Input0_16);
for (uint I = 0; I < 16; ++I)
Out[13 + I] = Result16[I];
}we get a vector bitcast and a vector load store https://hlsl.godbolt.org/z/Ydonf11ra
The important part of these tests being the %3 = bitcast <16 x i32> %2 to <16 x float> I wonder if it is worth reducing the hlsl code if it forces us to have to xfail Metal for DXC?
There was a problem hiding this comment.
We discussed offline. @bogner suggested just xfailing metal. I don't love this as metal is more convenient for me to test this feature on my local machine when using DXC and DXC does not support SPV_EXT_long_vector so we can't do local testing via SPIR-V either.
I do have the ability to remote into a windows machine, which I suppose is a fine way forward.
There was a problem hiding this comment.
FWIW while I do think having some test coverage of the vector rawBufferVectorLoad/Store is important and that using ByteAddressBuffer simplifies the tests, I'd be okay with most of these doing the more awkward code if it makes your life better.
That said, the metal shaderconverter definitely doesn't support all of long vector yet - I'm fairly surprised that any of the operations that actually lower to a dx.op.* with long vectors work there at all.
Fair I wrote a script to generate these using DXC for test case results. That's why they all test the same 3 vector sizes: https://gist.github.com/farzonl/63d53a32cc41f6b5af39b1a99ffd9a26 |
8d4aa85 to
210c469
Compare
bogner
left a comment
There was a problem hiding this comment.
Generally looks pretty good. Mostly have a bunch of nitpicks and a question or two.
| # Note We fail for DXC because today Clang scalairzed and does | ||
| # Not hit IRErrorCodeUnsupportedInstruction on vector @dx.op.* |
There was a problem hiding this comment.
I find this sentence a bit confusing (in addition to the typo and the odd whitespace). How about:
| # Note We fail for DXC because today Clang scalairzed and does | |
| # Not hit IRErrorCodeUnsupportedInstruction on vector @dx.op.* | |
| # Note that we only pass on clang because Clang scalarizes. We will hit | |
| # IRErrorCodeUnsupportedInstruction once Clang implements SM 6.10. |
There was a problem hiding this comment.
just deleted it. Comment isn't needed captured it instead in the issue.
| Out.Store<vector<double, 8> >(0, asdouble(In0.Load<vector<uint, 8> >(0), | ||
| In1.Load<vector<uint, 8> >(0))); |
There was a problem hiding this comment.
clang-format (once you convince it to use Style: c++03) says:
| Out.Store<vector<double, 8> >(0, asdouble(In0.Load<vector<uint, 8> >(0), | |
| In1.Load<vector<uint, 8> >(0))); | |
| Out.Store<vector<double, 8> >(0, asdouble(In0.Load<vector<uint, 8> >(0), | |
| In1.Load<vector<uint, 8> >(0))); |
There was a problem hiding this comment.
How did you do this when I run clang-format it changes up the yaml?
There was a problem hiding this comment.
I have a clang-format-region keybinding set up in my editor, otherwise it's a bit of a pain. You could run clang-format on the split files in the build directory but you may run into issues with shaders that use semantics in the arguments to the entry point, as those aren't handled very well by clang-format yet.
There was a problem hiding this comment.
I don't have that tried doing it with regular clang format. then tried writing a script that ran split file did the format then merged back, eventually I just gave up and updated my generator to just align multi argument intrinsics. I would rather not keep getting caught up on formatting for tests, but you let me know how it looks.
| Data: [0x4000, 0x3800, 0x0000, 0x3C00, 0xBC00, 0x4000, 0x3800, 0x0000, 0x3C00, 0xBC00, 0x4000, 0x3800, 0x0000, 0x3C00, 0xBC00, 0x4000] | ||
| # [ 2, 0.5, 0, 1, -1, 2, 0.5, 0, 1, -1, 2, 0.5, 0, 1, -1, 2] |
There was a problem hiding this comment.
aside (as in we don't need to change it here): it's really annoying that we use hex for float16 - it'd be nice to just use literals for exactly representable values like we do for float32
| Rule: BufferFloatEpsilon | ||
| Epsilon: 0.008 |
There was a problem hiding this comment.
Why choose epsilon over ULPs here (and elsewhere), and why 0.008? Is this how the precision of these ops is specified?
| Out.Store<vector<float, 5> >(0, clamp(In0.Load<vector<float, 5> >(0), | ||
| In1.Load<vector<float, 5> >(0), | ||
| In2.Load<vector<float, 5> >(0))); |
There was a problem hiding this comment.
| Out.Store<vector<float, 5> >(0, clamp(In0.Load<vector<float, 5> >(0), | |
| In1.Load<vector<float, 5> >(0), | |
| In2.Load<vector<float, 5> >(0))); | |
| Out.Store<vector<float, 5> >(0, clamp(In0.Load<vector<float, 5> >(0), | |
| In1.Load<vector<float, 5> >(0), | |
| In2.Load<vector<float, 5> >(0))); |
There was a problem hiding this comment.
I'm not really following what's happening in this test. I guess if clip(Input5) discarded the pixel then clip(Input8) and clip(Input16) are redundant, but also every value in each input is identical. Can you add some comments about what we're doing here and/or simplify the test?
| Out.Store<vector<double, 8> >(0, fma(In0.Load<vector<double, 8> >(0), | ||
| In1.Load<vector<double, 8> >(0), | ||
| In2.Load<vector<double, 8> >(0))); |
There was a problem hiding this comment.
More formatting. I'm going to stop pointing these out now but there are quite a few.
…ment intrinsics formated
210c469 to
e422c54
Compare
…ts on either intel or nvida gpu depending on intrinsic
resolves #1462
Assisted with GPT-5.6 Sol via Copilot