Testing Shader Buffer Read/Write Capabilities

You need the following Simdify® modules to complete this exercise: Simdify® Free Edition, Simdify® Compute Module, Simdify® Buffer Module

In this exercise you'll learn how to check if your GPU correctly reads and writes values to shader buffers. Driver bugs are infrequent and these tests let you know if there are problems you should be aware of. It's also worth mentioning that Scenomics uses these tests to verify our OpenGL implementation. We've found plenty of our own bugs this way.

Start The Layout application

  1. Start the Layout app. (Start » Programs » Scenomics » Layout) or (Windows® key and then type 'Layout' to find the app icon.)

    The application displays a splash screen and then the application desktop appears.

    This is a picture of the desktop.

Run Shader Buffer Write/Read Test Command

  1. Examine the main menu and select File » Run Tests.

    The application displays a list of tests that you can run.

  2. Select Spa.Test.ShaderBuffer from the listed options and click OK or hit ENTER when you are finished.

    This is going to determine if your GPU is capable of reading and writing shader buffer values correctly. Verification is performed by writing the values and then reading them back. We'll explore the test code later. Note that some GPUs do not support large shaders. If your GPU cannot compile this shader, you'll need to disable some of the code. That is discussed at the end of this exercise.

    //////////////////////////////////////////////////
    // Starting Shader Buffer Tests
    //////////////////////////////////////////////////
    
    Found test GLSL: D:\Release6\Content\Tests\GPU\Shader Buffer Read Write\test_shader_buffer_read_write.glsl
    Setting up program to run compute shader using GLSL #version 430.
    Successfully compiled shader program.
    Successfully set shader program active on rendering device.
    Validated binding index: 'test_buffer' buffer index is: 0
    Validated buffer size: 'test_buffer' buffer size is 104512 bytes.
    Successfully created buffer 'test_buffer' on device.
    
    //////////////////////////////////////////////////
    test_bool
    //////////////////////////////////////////////////
    
    a_bWrite is: true
    a_bRead is:  true
    
    Result of memcmp(): 0 [ 0 = passed, any non-zero = fail ]
    
    a_oInfo.Name............................test_bool
    a_oInfo.TypeCode........................GL_BOOL_ARB
    a_oInfo.TypeName........................bool
    a_oInfo.Index...........................0
    a_oInfo.BufferIndex.....................0
    a_oInfo.BufferBinding...................-1
    a_oInfo.BufferType......................4
    a_oInfo.Location........................-1
    a_oInfo.Offset..........................0
    a_oInfo.Size............................1
    a_oInfo.Type............................0x8b56
    a_oInfo.TypeSize........................4
    a_oInfo.ArrayStride.....................0
    a_oInfo.MatrixStride....................0
    a_oInfo.Rows............................0
    a_oInfo.Cols............................0
    a_oInfo.RowMajor........................0
    a_oInfo.TopLevelArraySize...............1
    a_oInfo.TopLevelArrayStride.............0
    a_oInfo.IsMemberOfTopLevelArray.........0
    a_oInfo.IsMemberOfTopLevelUnsizedArray..0
    a_oInfo.GetTotalSize....................4
    
    ...
    
    Executed: ApplicationRunTests
    
    test_bool test status: 0 [ 0 = passed, any non-zero = fail ]
    
    ...

    This is how you can verify that your hardware successfully reads and writes shader buffers.

Get The Test Code Path

  1. Select File » Get Application Script Path... from the main menu.

    The software displays a dialog that allows you to select a script.

    This is a picture of the desktop.
  2. Type app_service_test_shader_buffer_util.ssl and left click the script when it appears.
  3. Click OK or hit ENTER when you are finished.

    The software copies the full path to the script to the Windows¯ clipboard.

Examine The Test Code 'Execute' Function

  1. Start a text editor of your choice and select the option to open a file from disk.
  2. Select CTRL + V to paste the fragment shader file path (into the place in the dialog where you specify the file to open) and open the file.
  3. Use the text editor search feature to find a function named Execute. There are a few clearly delineated sections.
    1. Set up a shader program.
    2. Set up a shader buffer for testing.
    3. Set up a memory barrier.
    4. A section for testing a single function at a time.
    5. A section that performs all tests.
    ///////////////////////////////////////////////////////////////////////////////
    // function
    ///////////////////////////////////////////////////////////////////////////////
    
    function bool Execute( CommandPresentationModuleInfo commandInfo )
    {
       //////////////////////////////////////////////////
       // Verify Simdify-Package-Shader-Buffer exists.
       //////////////////////////////////////////////////
    
       if( !( SimdifyPackageShaderBuffer.Installed() ) )
       {
          string a_sPackage = SimdifyPackageShaderBuffer.GetName();
          string a_sMessage = "Required package <" + a_sPackage + "> is not installed.";
          LibAppServiceMessageBox.Alert( a_sMessage );
          return false;
       }
    
       //////////////////////////////////////////////////
       // Set up the shader program.
       //////////////////////////////////////////////////
    
       auto GpuTestDevice a_oParams;
    
       Render3D a_oAccel = Application.GetAccelerate3D();
       a_oParams.m_pAccel = a_oAccel;
    
       auto Program a_oProgram;
       a_oParams.m_pProgram = a_oProgram;
    
       // Create and bind the uniform buffer.
       a_oParams.m_sTestFolder = "Shader Buffer Read Write";
       a_oParams.m_sGlslTestFile = "test_shader_buffer_read_write.glsl";
       a_oParams.m_sBufferName = "test_buffer";
    
       a_oParams.m_slInfo.Add( LibAppServiceTest.Bar() );
       a_oParams.m_slInfo.Add( "// Starting Shader Buffer Tests" );
       a_oParams.m_slInfo.Add( LibAppServiceTest.Bar() );
       a_oParams.m_slInfo.AddBlank();
    
       bool a_bInit = LibAppServiceTest.Initialize( a_oParams );
       if( !( a_bInit ) )
       {
          return false;
       }
    
       Console.Clear();
    
       //////////////////////////////////////////////////
       // Create and bind the shader buffer.
       //////////////////////////////////////////////////
    
       auto ShaderBufferNode a_oShaderBuffer;
    
       auto ShaderBufferInfo a_oShaderBufferInfo;
       a_oShaderBufferInfo.m_pAccel = a_oAccel;
       a_oShaderBufferInfo.m_pRenderInfo = a_oParams.m_pRenderInfo;
       a_oShaderBufferInfo.m_pBuffer = a_oShaderBuffer;
       a_oShaderBufferInfo.m_pProgram = a_oProgram;
       a_oShaderBufferInfo.m_sBufferName = "test_buffer";
       a_oShaderBufferInfo.m_eBufferUsage = Enum.RBU_DynamicDraw();
    
       bool a_bCreatedBuffer = LibRender3D.CreateShaderBuffer(
          a_oShaderBufferInfo, a_oParams.m_slInfo );
    
       if( !( a_bCreatedBuffer ) )
       {
          a_oParams.m_slInfo.AddBlank();
          a_oParams.m_slInfo.Add( LibAssert.PrintCallStack() );
          LibAppServiceBuild.Out( a_oParams.m_slInfo );
          return false;
       }
    
       //////////////////////////////////////////////////
       // Set up the memory barrier.
       //////////////////////////////////////////////////
    
       // Since we're writing to a shader buffer, we
       // need to use a memory barrier between
       // accesses to the buffer.
       auto GpuMemoryBarrier m;
       m.GlShaderStorageBarrierBit = true;
    
       //////////////////////////////////////////////////
       // Declare subscripts for testing.
       //////////////////////////////////////////////////
    
       auto Int32Array a_aiSubs1;
       a_aiSubs1.Add( 2 );
    
       auto Int32Array a_aiSubs2;
       a_aiSubs2.Add( 2 );
       a_aiSubs2.Add( 3 );
    
       auto Int32Array a_aiSubs3;
       a_aiSubs3.Add( 2 );
       a_aiSubs3.Add( 3 );
       a_aiSubs3.Add( 4 );
    
       //////////////////////////////////////////////////
       // Execute single tests.
       //////////////////////////////////////////////////
    
       if( false )
       {
          TestFloat32MatrixArray( a_oParams, m, 2, 2, false, a_aiSubs1 );
    
          LibAppServiceBuild.Out( a_oParams.m_slInfo );
          Console.Out( "" );
          LibAppServiceBuild.Out( a_oParams.m_slTestStatus );
    
          // Do cleanup.
          //LibAppServiceMessageBox.Alert( "DESTROYING PROGRAM AND BUFFER!" );
          //Console.Out( a_oProgram.GetHandle() );
    
          a_oAccel.DeleteProgram( a_oProgram.GetHandle() );
          a_oAccel.DestroyShaderBuffer( a_oShaderBuffer.GetParams() );
          delete a_oParams.m_pRenderInfo;
    
          return false;
       }
    
       //////////////////////////////////////////////////
       // Execute all tests.
       //////////////////////////////////////////////////
    
       // Some of these tests require hardware that supports
       // the 8-bit signed/unsigned, 16-bit signed/unsigned
       // 16-bit FP, and 64-bit signed/unsigned extension.
    
       // Check extensions.
       RenderDeviceCaps a_oCaps = a_oAccel.GetDeviceCapabilities();
    
       bool a_bNvGpuShader5       = a_oCaps.QueryExtension( "GL_NV_gpu_shader5" );
       bool a_bAmdInt64           = a_oCaps.QueryExtension( "GL_AMD_gpu_shader_int64" );
       bool a_bArbInt64           = a_oCaps.QueryExtension( "GL_ARB_gpu_shader_int64" );
    
       bool a_bHighPrecInt  = a_bNvGpuShader5 || a_bAmdInt64 || a_bArbInt64;
       bool a_bLowPrecInt   = a_bNvGpuShader5;
       bool a_bLowPrecFloat = a_bNvGpuShader5;
    
       // Begin tests.
       TestBool( a_oParams, m );
       TestBoolArray( a_oParams, m, a_aiSubs1 );
       TestBoolArray( a_oParams, m, a_aiSubs2 );
       TestBoolArray( a_oParams, m, a_aiSubs3 );
       TestBoolVector( a_oParams, m, 2 );
       TestBoolVector( a_oParams, m, 3 );
       TestBoolVector( a_oParams, m, 4 );
       TestBoolVectorArray( a_oParams, m, 2, a_aiSubs1 );
       TestBoolVectorArray( a_oParams, m, 3, a_aiSubs1 );
       TestBoolVectorArray( a_oParams, m, 4, a_aiSubs1 );
       TestBoolVectorArray( a_oParams, m, 2, a_aiSubs2 );
       TestBoolVectorArray( a_oParams, m, 3, a_aiSubs2 );
       TestBoolVectorArray( a_oParams, m, 4, a_aiSubs2 );
       TestBoolVectorArray( a_oParams, m, 2, a_aiSubs3 );
       TestBoolVectorArray( a_oParams, m, 3, a_aiSubs3 );
       TestBoolVectorArray( a_oParams, m, 4, a_aiSubs3 );
    
       if( a_bLowPrecInt )
       {
          TestUint8( a_oParams, m );
          TestUint8Array( a_oParams, m, a_aiSubs1 );
          TestUint8Array( a_oParams, m, a_aiSubs2 );
          TestUint8Array( a_oParams, m, a_aiSubs3 );
          TestUint8Vector( a_oParams, m, 2 );
          TestUint8Vector( a_oParams, m, 3 );
          TestUint8Vector( a_oParams, m, 4 );
          TestUint8VectorArray( a_oParams, m, 2, a_aiSubs1 );
          TestUint8VectorArray( a_oParams, m, 3, a_aiSubs1 );
          TestUint8VectorArray( a_oParams, m, 4, a_aiSubs1 );
          TestUint8VectorArray( a_oParams, m, 2, a_aiSubs2 );
          TestUint8VectorArray( a_oParams, m, 3, a_aiSubs2 );
          TestUint8VectorArray( a_oParams, m, 4, a_aiSubs2 );
          TestUint8VectorArray( a_oParams, m, 2, a_aiSubs3 );
          TestUint8VectorArray( a_oParams, m, 3, a_aiSubs3 );
          TestUint8VectorArray( a_oParams, m, 4, a_aiSubs3 );
    
          TestUint16( a_oParams, m );
          TestUint16Array( a_oParams, m, a_aiSubs1 );
          TestUint16Array( a_oParams, m, a_aiSubs2 );
          TestUint16Array( a_oParams, m, a_aiSubs3 );
          TestUint16Vector( a_oParams, m, 2 );
          TestUint16Vector( a_oParams, m, 3 );
          TestUint16Vector( a_oParams, m, 4 );
          TestUint16VectorArray( a_oParams, m, 2, a_aiSubs1 );
          TestUint16VectorArray( a_oParams, m, 3, a_aiSubs1 );
          TestUint16VectorArray( a_oParams, m, 4, a_aiSubs1 );
          TestUint16VectorArray( a_oParams, m, 2, a_aiSubs2 );
          TestUint16VectorArray( a_oParams, m, 3, a_aiSubs2 );
          TestUint16VectorArray( a_oParams, m, 4, a_aiSubs2 );
          TestUint16VectorArray( a_oParams, m, 2, a_aiSubs3 );
          TestUint16VectorArray( a_oParams, m, 3, a_aiSubs3 );
          TestUint16VectorArray( a_oParams, m, 4, a_aiSubs3 );
       }
    
       TestUint32( a_oParams, m );
       TestUint32Array( a_oParams, m, a_aiSubs1 );
       TestUint32Array( a_oParams, m, a_aiSubs2 );
       TestUint32Array( a_oParams, m, a_aiSubs3 );
       TestUint32Vector( a_oParams, m, 2 );
       TestUint32Vector( a_oParams, m, 3 );
       TestUint32Vector( a_oParams, m, 4 );
       TestUint32VectorArray( a_oParams, m, 2, a_aiSubs1 );
       TestUint32VectorArray( a_oParams, m, 3, a_aiSubs1 );
       TestUint32VectorArray( a_oParams, m, 4, a_aiSubs1 );
       TestUint32VectorArray( a_oParams, m, 2, a_aiSubs2 );
       TestUint32VectorArray( a_oParams, m, 3, a_aiSubs2 );
       TestUint32VectorArray( a_oParams, m, 4, a_aiSubs2 );
       TestUint32VectorArray( a_oParams, m, 2, a_aiSubs3 );
       TestUint32VectorArray( a_oParams, m, 3, a_aiSubs3 );
       TestUint32VectorArray( a_oParams, m, 4, a_aiSubs3 );
    
       if( a_bHighPrecInt )
       {
          TestUint64( a_oParams, m );
          TestUint64Array( a_oParams, m, a_aiSubs1 );
          TestUint64Array( a_oParams, m, a_aiSubs2 );
          TestUint64Array( a_oParams, m, a_aiSubs3 );
          TestUint64Vector( a_oParams, m, 2 );
          TestUint64Vector( a_oParams, m, 3 );
          TestUint64Vector( a_oParams, m, 4 );
          TestUint64VectorArray( a_oParams, m, 2, a_aiSubs1 );
          TestUint64VectorArray( a_oParams, m, 3, a_aiSubs1 );
          TestUint64VectorArray( a_oParams, m, 4, a_aiSubs1 );
          TestUint64VectorArray( a_oParams, m, 2, a_aiSubs2 );
          TestUint64VectorArray( a_oParams, m, 3, a_aiSubs2 );
          TestUint64VectorArray( a_oParams, m, 4, a_aiSubs2 );
          TestUint64VectorArray( a_oParams, m, 2, a_aiSubs3 );
          TestUint64VectorArray( a_oParams, m, 3, a_aiSubs3 );
          TestUint64VectorArray( a_oParams, m, 4, a_aiSubs3 );
       }
    
       if( a_bLowPrecInt )
       {
          TestInt8( a_oParams, m );
          TestInt8Array( a_oParams, m, a_aiSubs1 );
          TestInt8Array( a_oParams, m, a_aiSubs2 );
          TestInt8Array( a_oParams, m, a_aiSubs3 );
          TestInt8Vector( a_oParams, m, 2 );
          TestInt8Vector( a_oParams, m, 3 );
          TestInt8Vector( a_oParams, m, 4 );
          TestInt8VectorArray( a_oParams, m, 2, a_aiSubs1 );
          TestInt8VectorArray( a_oParams, m, 3, a_aiSubs1 );
          TestInt8VectorArray( a_oParams, m, 4, a_aiSubs1 );
          TestInt8VectorArray( a_oParams, m, 2, a_aiSubs2 );
          TestInt8VectorArray( a_oParams, m, 3, a_aiSubs2 );
          TestInt8VectorArray( a_oParams, m, 4, a_aiSubs2 );
          TestInt8VectorArray( a_oParams, m, 2, a_aiSubs3 );
          TestInt8VectorArray( a_oParams, m, 3, a_aiSubs3 );
          TestInt8VectorArray( a_oParams, m, 4, a_aiSubs3 );
    
          TestInt16( a_oParams, m );
          TestInt16Array( a_oParams, m, a_aiSubs1 );
          TestInt16Array( a_oParams, m, a_aiSubs2 );
          TestInt16Array( a_oParams, m, a_aiSubs3 );
          TestInt16Vector( a_oParams, m, 2 );
          TestInt16Vector( a_oParams, m, 3 );
          TestInt16Vector( a_oParams, m, 4 );
          TestInt16VectorArray( a_oParams, m, 2, a_aiSubs1 );
          TestInt16VectorArray( a_oParams, m, 3, a_aiSubs1 );
          TestInt16VectorArray( a_oParams, m, 4, a_aiSubs1 );
          TestInt16VectorArray( a_oParams, m, 2, a_aiSubs2 );
          TestInt16VectorArray( a_oParams, m, 3, a_aiSubs2 );
          TestInt16VectorArray( a_oParams, m, 4, a_aiSubs2 );
          TestInt16VectorArray( a_oParams, m, 2, a_aiSubs3 );
          TestInt16VectorArray( a_oParams, m, 3, a_aiSubs3 );
          TestInt16VectorArray( a_oParams, m, 4, a_aiSubs3 );
       }
    
       TestInt32( a_oParams, m );
       TestInt32Array( a_oParams, m, a_aiSubs1 );
       TestInt32Array( a_oParams, m, a_aiSubs2 );
       TestInt32Array( a_oParams, m, a_aiSubs3 );
       TestInt32Vector( a_oParams, m, 2 );
       TestInt32Vector( a_oParams, m, 3 );
       TestInt32Vector( a_oParams, m, 4 );
       TestInt32VectorArray( a_oParams, m, 2, a_aiSubs1 );
       TestInt32VectorArray( a_oParams, m, 3, a_aiSubs1 );
       TestInt32VectorArray( a_oParams, m, 4, a_aiSubs1 );
       TestInt32VectorArray( a_oParams, m, 2, a_aiSubs2 );
       TestInt32VectorArray( a_oParams, m, 3, a_aiSubs2 );
       TestInt32VectorArray( a_oParams, m, 4, a_aiSubs2 );
       TestInt32VectorArray( a_oParams, m, 2, a_aiSubs3 );
       TestInt32VectorArray( a_oParams, m, 3, a_aiSubs3 );
       TestInt32VectorArray( a_oParams, m, 4, a_aiSubs3 );
    
       if( a_bHighPrecInt )
       {
          TestInt64( a_oParams, m );
          TestInt64Array( a_oParams, m, a_aiSubs1 );
          TestInt64Array( a_oParams, m, a_aiSubs2 );
          TestInt64Array( a_oParams, m, a_aiSubs3 );
          TestInt64Vector( a_oParams, m, 2 );
          TestInt64Vector( a_oParams, m, 3 );
          TestInt64Vector( a_oParams, m, 4 );
          TestInt64VectorArray( a_oParams, m, 2, a_aiSubs1 );
          TestInt64VectorArray( a_oParams, m, 3, a_aiSubs1 );
          TestInt64VectorArray( a_oParams, m, 4, a_aiSubs1 );
          TestInt64VectorArray( a_oParams, m, 2, a_aiSubs2 );
          TestInt64VectorArray( a_oParams, m, 3, a_aiSubs2 );
          TestInt64VectorArray( a_oParams, m, 4, a_aiSubs2 );
          TestInt64VectorArray( a_oParams, m, 2, a_aiSubs3 );
          TestInt64VectorArray( a_oParams, m, 3, a_aiSubs3 );
          TestInt64VectorArray( a_oParams, m, 4, a_aiSubs3 );
       }
    
       if( a_bLowPrecFloat )
       {
          TestFloat16( a_oParams, m );
          TestFloat16Array( a_oParams, m, a_aiSubs1 );
          TestFloat16Array( a_oParams, m, a_aiSubs2 );
          TestFloat16Array( a_oParams, m, a_aiSubs3 );
          TestFloat16Vector( a_oParams, m, 2 );
          TestFloat16Vector( a_oParams, m, 3 );
          TestFloat16Vector( a_oParams, m, 4 );
          TestFloat16VectorArray( a_oParams, m, 2, a_aiSubs1 );
          TestFloat16VectorArray( a_oParams, m, 3, a_aiSubs1 );
          TestFloat16VectorArray( a_oParams, m, 4, a_aiSubs1 );
          TestFloat16VectorArray( a_oParams, m, 2, a_aiSubs2 );
          TestFloat16VectorArray( a_oParams, m, 3, a_aiSubs2 );
          TestFloat16VectorArray( a_oParams, m, 4, a_aiSubs2 );
          TestFloat16VectorArray( a_oParams, m, 2, a_aiSubs3 );
          TestFloat16VectorArray( a_oParams, m, 3, a_aiSubs3 );
          TestFloat16VectorArray( a_oParams, m, 4, a_aiSubs3 );
       }
    
       TestFloat32( a_oParams, m );
       TestFloat32Array( a_oParams, m, a_aiSubs1 );
       TestFloat32Array( a_oParams, m, a_aiSubs2 );
       TestFloat32Array( a_oParams, m, a_aiSubs3 );
       TestFloat32Vector( a_oParams, m, 2 );
       TestFloat32Vector( a_oParams, m, 3 );
       TestFloat32Vector( a_oParams, m, 4 );
       TestFloat32VectorArray( a_oParams, m, 2, a_aiSubs1 );
       TestFloat32VectorArray( a_oParams, m, 3, a_aiSubs1 );
       TestFloat32VectorArray( a_oParams, m, 4, a_aiSubs1 );
       TestFloat32VectorArray( a_oParams, m, 2, a_aiSubs2 );
       TestFloat32VectorArray( a_oParams, m, 3, a_aiSubs2 );
       TestFloat32VectorArray( a_oParams, m, 4, a_aiSubs2 );
       TestFloat32VectorArray( a_oParams, m, 2, a_aiSubs3 );
       TestFloat32VectorArray( a_oParams, m, 3, a_aiSubs3 );
       TestFloat32VectorArray( a_oParams, m, 4, a_aiSubs3 );
    
       // Column Major
       TestFloat32Matrix( a_oParams, m, 2, 2, false );
       TestFloat32Matrix( a_oParams, m, 2, 3, false );
       TestFloat32Matrix( a_oParams, m, 2, 4, false );
       TestFloat32Matrix( a_oParams, m, 3, 2, false );
       TestFloat32Matrix( a_oParams, m, 3, 3, false );
       TestFloat32Matrix( a_oParams, m, 3, 4, false );
       TestFloat32Matrix( a_oParams, m, 4, 2, false );
       TestFloat32Matrix( a_oParams, m, 4, 3, false );
       TestFloat32Matrix( a_oParams, m, 4, 4, false );
    
       // Row Major
       TestFloat32Matrix( a_oParams, m, 2, 2, true );
       TestFloat32Matrix( a_oParams, m, 2, 3, true );
       TestFloat32Matrix( a_oParams, m, 2, 4, true );
       TestFloat32Matrix( a_oParams, m, 3, 2, true );
       TestFloat32Matrix( a_oParams, m, 3, 3, true );
       TestFloat32Matrix( a_oParams, m, 3, 4, true );
       TestFloat32Matrix( a_oParams, m, 4, 2, true );
       TestFloat32Matrix( a_oParams, m, 4, 3, true );
       TestFloat32Matrix( a_oParams, m, 4, 4, true );
    
       // Column Major
       TestFloat32MatrixArray( a_oParams, m, 2, 2, false, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 2, 2, false, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 2, 2, false, a_aiSubs3 );
       TestFloat32MatrixArray( a_oParams, m, 2, 3, false, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 2, 3, false, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 2, 3, false, a_aiSubs3 );
       TestFloat32MatrixArray( a_oParams, m, 2, 4, false, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 2, 4, false, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 2, 4, false, a_aiSubs3 );
       TestFloat32MatrixArray( a_oParams, m, 3, 2, false, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 3, 2, false, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 3, 2, false, a_aiSubs3 );
       TestFloat32MatrixArray( a_oParams, m, 3, 3, false, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 3, 3, false, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 3, 3, false, a_aiSubs3 );
       TestFloat32MatrixArray( a_oParams, m, 3, 4, false, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 3, 4, false, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 3, 4, false, a_aiSubs3 );
       TestFloat32MatrixArray( a_oParams, m, 4, 2, false, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 4, 2, false, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 4, 2, false, a_aiSubs3 );
       TestFloat32MatrixArray( a_oParams, m, 4, 3, false, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 4, 3, false, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 4, 3, false, a_aiSubs3 );
       TestFloat32MatrixArray( a_oParams, m, 4, 4, false, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 4, 4, false, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 4, 4, false, a_aiSubs3 );
    
       // Row Major
       TestFloat32MatrixArray( a_oParams, m, 2, 2, true, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 2, 2, true, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 2, 2, true, a_aiSubs3 );
       TestFloat32MatrixArray( a_oParams, m, 2, 3, true, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 2, 3, true, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 2, 3, true, a_aiSubs3 );
       TestFloat32MatrixArray( a_oParams, m, 2, 4, true, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 2, 4, true, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 2, 4, true, a_aiSubs3 );
       TestFloat32MatrixArray( a_oParams, m, 3, 2, true, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 3, 2, true, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 3, 2, true, a_aiSubs3 );
       TestFloat32MatrixArray( a_oParams, m, 3, 3, true, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 3, 3, true, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 3, 3, true, a_aiSubs3 );
       TestFloat32MatrixArray( a_oParams, m, 3, 4, true, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 3, 4, true, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 3, 4, true, a_aiSubs3 );
       TestFloat32MatrixArray( a_oParams, m, 4, 2, true, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 4, 2, true, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 4, 2, true, a_aiSubs3 );
       TestFloat32MatrixArray( a_oParams, m, 4, 3, true, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 4, 3, true, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 4, 3, true, a_aiSubs3 );
       TestFloat32MatrixArray( a_oParams, m, 4, 4, true, a_aiSubs1 );
       TestFloat32MatrixArray( a_oParams, m, 4, 4, true, a_aiSubs2 );
       TestFloat32MatrixArray( a_oParams, m, 4, 4, true, a_aiSubs3 );
    
       TestFloat64( a_oParams, m );
       TestFloat64Array( a_oParams, m, a_aiSubs1 );
       TestFloat64Array( a_oParams, m, a_aiSubs2 );
       TestFloat64Array( a_oParams, m, a_aiSubs3 );
       TestFloat64Vector( a_oParams, m, 2 );
       TestFloat64Vector( a_oParams, m, 3 );
       TestFloat64Vector( a_oParams, m, 4 );
       TestFloat64VectorArray( a_oParams, m, 2, a_aiSubs1 );
       TestFloat64VectorArray( a_oParams, m, 3, a_aiSubs1 );
       TestFloat64VectorArray( a_oParams, m, 4, a_aiSubs1 );
       TestFloat64VectorArray( a_oParams, m, 2, a_aiSubs2 );
       TestFloat64VectorArray( a_oParams, m, 3, a_aiSubs2 );
       TestFloat64VectorArray( a_oParams, m, 4, a_aiSubs2 );
       TestFloat64VectorArray( a_oParams, m, 2, a_aiSubs3 );
       TestFloat64VectorArray( a_oParams, m, 3, a_aiSubs3 );
       TestFloat64VectorArray( a_oParams, m, 4, a_aiSubs3 );
    
       // Column Major
       TestFloat64Matrix( a_oParams, m, 2, 2, false );
       TestFloat64Matrix( a_oParams, m, 2, 3, false );
       TestFloat64Matrix( a_oParams, m, 2, 4, false );
       TestFloat64Matrix( a_oParams, m, 3, 2, false );
       TestFloat64Matrix( a_oParams, m, 3, 3, false );
       TestFloat64Matrix( a_oParams, m, 3, 4, false );
       TestFloat64Matrix( a_oParams, m, 4, 2, false );
       TestFloat64Matrix( a_oParams, m, 4, 3, false );
       TestFloat64Matrix( a_oParams, m, 4, 4, false );
    
       // Row Major
       TestFloat64Matrix( a_oParams, m, 2, 2, true );
       TestFloat64Matrix( a_oParams, m, 2, 3, true );
       TestFloat64Matrix( a_oParams, m, 2, 4, true );
       TestFloat64Matrix( a_oParams, m, 3, 2, true );
       TestFloat64Matrix( a_oParams, m, 3, 3, true );
       TestFloat64Matrix( a_oParams, m, 3, 4, true );
       TestFloat64Matrix( a_oParams, m, 4, 2, true );
       TestFloat64Matrix( a_oParams, m, 4, 3, true );
       TestFloat64Matrix( a_oParams, m, 4, 4, true );
    
       // Column Major
       TestFloat64MatrixArray( a_oParams, m, 2, 2, false, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 2, 2, false, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 2, 2, false, a_aiSubs3 );
       TestFloat64MatrixArray( a_oParams, m, 2, 3, false, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 2, 3, false, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 2, 3, false, a_aiSubs3 );
       TestFloat64MatrixArray( a_oParams, m, 2, 4, false, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 2, 4, false, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 2, 4, false, a_aiSubs3 );
       TestFloat64MatrixArray( a_oParams, m, 3, 2, false, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 3, 2, false, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 3, 2, false, a_aiSubs3 );
       TestFloat64MatrixArray( a_oParams, m, 3, 3, false, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 3, 3, false, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 3, 3, false, a_aiSubs3 );
       TestFloat64MatrixArray( a_oParams, m, 3, 4, false, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 3, 4, false, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 3, 4, false, a_aiSubs3 );
       TestFloat64MatrixArray( a_oParams, m, 4, 2, false, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 4, 2, false, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 4, 2, false, a_aiSubs3 );
       TestFloat64MatrixArray( a_oParams, m, 4, 3, false, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 4, 3, false, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 4, 3, false, a_aiSubs3 );
       TestFloat64MatrixArray( a_oParams, m, 4, 4, false, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 4, 4, false, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 4, 4, false, a_aiSubs3 );
    
       // Row Major
       TestFloat64MatrixArray( a_oParams, m, 2, 2, true, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 2, 2, true, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 2, 2, true, a_aiSubs3 );
       TestFloat64MatrixArray( a_oParams, m, 2, 3, true, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 2, 3, true, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 2, 3, true, a_aiSubs3 );
       TestFloat64MatrixArray( a_oParams, m, 2, 4, true, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 2, 4, true, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 2, 4, true, a_aiSubs3 );
       TestFloat64MatrixArray( a_oParams, m, 3, 2, true, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 3, 2, true, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 3, 2, true, a_aiSubs3 );
       TestFloat64MatrixArray( a_oParams, m, 3, 3, true, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 3, 3, true, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 3, 3, true, a_aiSubs3 );
       TestFloat64MatrixArray( a_oParams, m, 3, 4, true, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 3, 4, true, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 3, 4, true, a_aiSubs3 );
       TestFloat64MatrixArray( a_oParams, m, 4, 2, true, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 4, 2, true, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 4, 2, true, a_aiSubs3 );
       TestFloat64MatrixArray( a_oParams, m, 4, 3, true, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 4, 3, true, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 4, 3, true, a_aiSubs3 );
       TestFloat64MatrixArray( a_oParams, m, 4, 4, true, a_aiSubs1 );
       TestFloat64MatrixArray( a_oParams, m, 4, 4, true, a_aiSubs2 );
       TestFloat64MatrixArray( a_oParams, m, 4, 4, true, a_aiSubs3 );
    
       // Do cleanup.
       //LibAppServiceMessageBox.Alert( "DESTROYING PROGRAM AND BUFFER!" );
       a_oAccel.DeleteProgram( a_oProgram.GetHandle() );
       a_oAccel.DestroyShaderBuffer( a_oShaderBuffer.GetParams() );
    
       delete a_oParams.m_pRenderInfo;
    
       //////////////////////////////////////////////////
       // Finis~
       //////////////////////////////////////////////////
    
       LibAppServiceBuild.Out( a_oParams.m_slInfo );
    
       Console.Blank();
       Console.Out( "Executed: " + Script.Runtime.CurrentFunction.Name );
       Console.Blank();
    
       LibAppServiceBuild.Out( a_oParams.m_slTestStatus );
    
       /*
       auto FilePath a_oTestOutputLogPath =
          new FilePath( "C:\\shader_buffer_log.txt" );
       WriteLog( a_oTestOutputLogPath, a_oParams.m_slTestStatus );
    
       auto FilePath a_oDetailsOutputLogPath =
          new FilePath( "C:\\shader_buffer_test_results.txt" );
       WriteLog( a_oDetailsOutputLogPath, a_oParams.m_slInfo );
       */
    
       return true;
    }
    

Examine The Test Code 'TestFloat32Matrix' Function

  1. Use the text editor search feature to find a function named TestFloat32Matrix. There are a few key sections.

    1. Create the variable name.
    2. Get reflection information for the buffer variable or return upon failure.
    3. Create the data we want to write and declare storage for the readback.
    4. Write data the device and execute the shader program.
    5. Read back the values that were written to the shader buffer variable during program execution.
    6. Print data.
    7. Print test results.
    8. Print shader buffer variable reflection information.

    ///////////////////////////////////////////////////////////////////////////////
    // function
    ///////////////////////////////////////////////////////////////////////////////
    
    function void TestFloat32Matrix( GpuTestDevice p_oTest, GpuMemoryBarrier m, int p_nCols, int p_nRows, bool p_bRowMajor )
    {
       string a_sName = "test_mat" + p_nCols + "x" + p_nRows;
       a_sName += AppendMatrixLayout( p_bRowMajor );
    
       LibAppServiceTest.MakeHeader(
          p_oTest.m_slInfo, a_sName, "" );
    
       auto ProgramConstantInfo a_oInfo;
       bool a_bValid = GetConstantInfo( p_oTest, a_oInfo, a_sName );
       if( !( a_bValid ) )
       {
          return;
       }
    
       ////////////////////////////////////////
       // Create Data
       ////////////////////////////////////////
    
       auto Float32ArrayAlgorithms a_afAlgorithms;
       auto Float32MatrixAlgorithms a_mfAlgorithms;
    
       auto Float32Matrix a_mfWrite;
       a_mfWrite.Fill( 0.0 );
    
       LibFloat32Matrix.Iota( a_mfWrite, p_nCols, p_nRows );
    
       auto Float32Matrix a_mfRead;
       a_mfRead.Fill( 0.0 );
    
       auto Float32ArrayView src_view = a_mfWrite.GetView();
       auto Float32ArrayView dst_view = a_mfRead.GetView();
    
       ////////////////////////////////////////
       // Write Data
       ////////////////////////////////////////
    
       bool a_bZeroMemory = true;
    
       int a_nWriteSize = a_mfAlgorithms.GetWriteSizeInBytes(
          a_oInfo, a_mfWrite, p_nCols, p_nRows );
       //LibAppServiceMessageBox.Alert( a_nWriteSize );
    
       auto Float32Array a_afWriteData;
       a_afWriteData.ConvertBytesToCount( a_nWriteSize );
       auto Float32Iterator it_dst = a_afWriteData.First();
    
       a_mfAlgorithms.ConvertToGpuMemoryLayout(
          a_oInfo, a_bZeroMemory, p_nCols, p_nRows,
          src_view.First, src_view.Last, it_dst );
       //LibFloat32Array.Out( a_afWriteData );
    
       auto MemoryPointer a_oSrcPtr = a_afWriteData.GetPointer();
    
       p_oTest.m_pAccel.WriteShaderSubBuffer(
          a_oInfo.Offset, a_nWriteSize, a_oSrcPtr );
    
       ////////////////////////////////////////
       // Execute Program
       ////////////////////////////////////////
    
       p_oTest.m_pAccel.ExecuteProgram( true, 128, 128, 1, 32, 32, 1 );
       p_oTest.m_pAccel.InsertMemoryBarrier( m );
    
       ////////////////////////////////////////
       // Read Data
       ////////////////////////////////////////
    
       auto Float32Array a_afReadData;
       a_afReadData.Count = a_afWriteData.GetCount();
       a_afReadData.Fill( 0.0 );
    
       auto MemoryPointer a_oDstPtr = a_afReadData.GetPointer();
    
       p_oTest.m_pAccel.ReadShaderSubBuffer(
          a_oInfo.Offset, a_oDstPtr.SizeInBytes(), a_oDstPtr );
       //LibFloat32Array.Out( a_afReadData );
    
       auto Float32ArrayView read_view = a_afReadData.GetView();
    
       a_mfAlgorithms.ConvertToCpuMemoryLayout(
          a_oInfo, a_bZeroMemory, p_nCols, p_nRows,
          read_view.First, read_view.Last, dst_view.First );
    
       ////////////////////////////////////////
       // Test Data
       ////////////////////////////////////////
    
       p_oTest.m_slInfo.Add( "Write values:" );
    
       LibFloat32Matrix.ConvertToCsv(
          a_mfWrite, p_oTest.m_slInfo );
    
       p_oTest.m_slInfo.AddBlank();
    
       p_oTest.m_slInfo.Add( "Read values:" );
       LibFloat32Matrix.ConvertToCsv(
          a_mfRead, p_oTest.m_slInfo );
    
       int a_nRes = a_afAlgorithms.Memcmp(
          src_view.First, dst_view.First, a_mfWrite.SizeInBytes() );
       LibAppServiceTest.DoMemcmp( p_oTest.m_slInfo, a_nRes );
    
       LibProgramConstantInfo.Print( a_oInfo, p_oTest.m_slInfo );
    
       p_oTest.m_slTestStatus.Add( a_sName + " test status: " +
          a_nRes + LibAppServiceTest.GetTestHint() );
    }