Graphics
Intel® graphics drivers and software, compatibility, troubleshooting, performance, and optimization
20895 Discussions

Compute shader producing incorrect output

David_Eberly
New Contributor I
2,147 Views

I have a GLSL compute shader designed to compute the distance between two line segments.  The output on Intel HD 4600 is incorrect, whereas I get the correct results on NVIDIA/AMD cards.

4th Generation Intel® Core™ Processors with Intel® HD Graphics 5000/4600/4400/4200
System Used:  Dell Inc. Precision T1700
CPU SKU: i7
GPU SKU: 4600
Processor Line: N/A
System BIOS Version: A16
CMOS settings: N/A
Graphics Driver Version: 10.18.15.4281
GOP/VBIOS Version: N/A
Operating System: Windows 10 Pro 64-bit
OS Version: (10.0, Build 10586) (10586.th2_release.160104-1513)
API: OpenGL 4.3.0
Occurs on non-Intel GPUs?:  No (tested on NVIDIA and AMD)

Steps to Reproduce:
I have provided a stand-alone Microsoft Visual Studio 2015
project that illustrates the problem.  The GLSL file
DistanceSegments.glsl computes the distance between two line
segments in 3D.

Expected Results:  Comments at the end of DistanceBug.cpp show
the correct results for a pair of segments.  The answers are
exact, and NVIDIA and AMD OpenGL drivers are computing the correct
results.

Actual Results: Comments at the end of DistanceBug.cpp show that
the Intel OpenGL driver is producing incorrect results.

Additional Information:
I created a project that executes the HLSL equivalent for Direct3D 11
and the results are correct on the Intel driver.  However, I originally
saw this problem in a somewhat more complicated scenario where I was
computing segment-segment distances for batches of segments.  In that
scenario, even the Intel Direct3D 11 driver was producing incorrect
results.  I will try to create a project that reduces that scenario
to a minimum set of code.

0 Kudos
6 Replies
Michael_C_Intel2
Employee
2,147 Views

Hi Dave,

Thanks for giving me all the details and the project for reproducing the problem. I will update you when we know something.

-Michael

0 Kudos
David_Eberly
New Contributor I
2,147 Views

Thanks for taking care of filing the reports.

Although not that important, I appear to show up as "Logged in as (name withheld)".  My profile actually shows me as (name withheld).  I tried to edit this to my real name but to no avail.  Any idea how I can change this?  Thanks.

 

0 Kudos
Michael_C_Intel2
Employee
2,147 Views

Hi Dave,

We have identified a bug in the driver and are working on a fix. Also we found a bug in the shader code.

Your code assumes a particular memory layout of variables inside Result structure that you shouldn't, as the default is layout(shared) which gives the freedom to use different layout, and we do so (at least with USC - on Gen7.5 and Gen8).

Proposed fix: If you change shader code by adding layout(std430), the layout of Result structure on GPU will be the same as expected in C++.

layout(std430) buffer outResult { Result data[]; } outResultSB;

For details, please refer to OpenGL specification chapter 7.6.2.2, page 138 or following page:
https://www.opengl.org/wiki/Interface_Block_(GLSL)#Memory_layout

Hope this help,

-Michael

0 Kudos
David_Eberly
New Contributor I
2,147 Views

Hello Michael.

Thank you for the report.  When I reduced the code and shader to a minimum set for posting, I forgot that my GLSL compiler-linker wrapper prepends some strings to those in the *.glsl file.  The first is the "#version 430", which I included in the file I posted.  The second string, which I failed to include in the shader I posted to you, is "layout(std430) buffer;" that specifies the layout to be used by all buffers in the shader.  I modified the shader I sent to you to include this second string and the layout appears to be correct now.  However, the results are still incorrect, which I assume relates to your comment about finding a driver bug.

Dave

0 Kudos
Michael_C_Intel2
Employee
2,147 Views

Hi Dave,

Thanks for the update, the engineer investigating the issue has some info to pass along:

You assume indices of the two SSBO to be {0, 1}, which is not guaranteed. To fix it, choose one of these solutions:

1. Ask OpenGL for SSBO indices using glGetProgramResourceIndex and use them, by changing code to:

GLuint inSegmentIndex = glGetProgramResourceIndex(programHandle, GL_SHADER_STORAGE_BLOCK, "inSegment");

GLuint outResultIndex = glGetProgramResourceIndex(programHandle, GL_SHADER_STORAGE_BLOCK, "outResult");

GLuint inSegmentBinding = 0;

GLuint outResultBinding = 1;

// Execute the compute shader.

glUseProgram(programHandle);

glShaderStorageBlockBinding(programHandle, inSegmentIndex, inSegmentBinding);

glBindBufferRange(GL_SHADER_STORAGE_BUFFER, inSegmentBinding, inSegmentHandle, 0, 2 * sizeof(Segment));

glShaderStorageBlockBinding(programHandle, outResultIndex, outResultBinding);

glBindBufferRange(GL_SHADER_STORAGE_BUFFER, outResultBinding, outResultHandle, 0, sizeof(Result));

glDispatchCompute(1, 1, 1);

glBindBufferBase(GL_SHADER_STORAGE_BUFFER, inSegmentBinding, 0);

glBindBufferBase(GL_SHADER_STORAGE_BUFFER, outResultBinding, 0);

glUseProgram(0);

 

2. Remove calls to glShaderStorageBlockBinding and specify binding in GLSL instead, by adding:

layout(std430, binding=0) buffer inSegment { Segment data[]; } inSegmentSB;

layout(std430, binding=1) buffer outResult { Result data[]; } outResultSB;

 

-Michael

0 Kudos
David_Eberly
New Contributor I
2,147 Views

Hello Michael.

Thanks for the details about the buffers.  Other parts of the engine are designed to require the shader writers to specify the bind points.  I need to check with the engineer who wrote the code to understand why buffers were handled differently.  He developed using AMD graphics and I diagnosed problems in the design when it depended on how AMD does things (I tested on Intel Graphics and NVIDIA).  It appears AMD assigns binding points to resources in order of occurrence, whereas NVIDIA appears to assign based on alphabetical sorting.

Dave

0 Kudos
Reply