1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
function DatapixxGPUDitherpatternTest(fullscreen, useVulkan)
% DatapixxGPUDitherpatternTest([fullscreen=1][, useVulkan=0])
%
% Low level diagnostic for GPU dithering via a VPixx
% devices like Datapixx/ViewPixx/Propixx, or a CRS
% device like the Bits# - but *not* the original Bits+.
%
% Steps through all 256 grayscale levels and uses
% Datapixx et al. scanline readback to check what
% the GPU actually outputs. Plots it and prints
% the first 10 pixels of the topmost output scanline.
%
% This is meant to facilitate low-level diagnosis
% of GPU dithering bugs if our regular test script
% BitsPlusIdentityClutTest.m reports dithering trouble
% and can't fix the problem automatically.
%
% 'fullscreen' Defaults to 1 for fullscreen windows.
% 0 = Use a windowed window at top of screen for
% display to also diagnose possible compositor
% interference.
%
% 'useVulkan' Defaults to 0. If set to 1, use Vulkan display
% backend, instead of standard OpenGL backend.
%
% History:
% 13-Aug-2015 mk Wrote it.
% 03-Jul-2016 mk Add support for CRS Bits#.
% 01-Sep-2020 mk Add support for Vulkan.
PsychDefaultSetup(0);
if nargin < 1 || isempty(fullscreen)
fullscreen = 1;
end
if nargin < 2 || isempty(useVulkan)
useVulkan = 0;
end
screenid = max(Screen('Screens'));
oldsynclevel = Screen('Preference', 'SkipSynctests', 1);
if fullscreen
rect = [];
else
rect = [0, 0, Screen('WindowSize', screenid), 90];
end
if BitsPlusPlus('OpenBits#')
BitsPlusPlus('SwitchToStatusScreen');
WaitSecs(4);
bitssharp = 1;
else
Datapixx('Open');
bitssharp = 0;
end
if useVulkan
PsychImaging('PrepareConfiguration');
PsychImaging('AddTask', 'General', 'UseVulkanDisplay');
w = PsychImaging('Openwindow', screenid, 0, rect);
else
w = Screen('Openwindow', screenid, 0, rect);
end
LoadIdentityClut(w);
%lut = Screen('Readnormalizedgammatable', screenid);
%foo1 = isequal(lut(:,1), lut(:,2))
%foo2 = isequal(lut(:,1), lut(:,3))
%close all;
%plot(lut);
even = zeros(1,256);
odd = even;
trouble = 0;
fprintf('\n\n\n\n');
KbReleaseWait(-1);
for i = 0:255
Screen('FillRect', w, i);
Screen('Flip', w);
if bitssharp
WaitSecs('YieldSecs', 3 * Screen('GetFlipInterval', w));
% Readback the two topmost scanlines from Bits# :
pixels = BitsPlusPlus('GetVideoLine', 256, 1);
pixels = [pixels, BitsPlusPlus('GetVideoLine', 256, 2)]; %#ok<AGROW>
else
Datapixx('RegWrRdVideoSync');
Datapixx('RegWrRdVideoSync');
Datapixx('RegWrRdVideoSync');
pixels = Datapixx('GetVideoLine');
end
fprintf('Ref %i: RGB ', i);
fprintf('%i ', pixels(:,[1:10, floor(length(pixels)/2):floor(length(pixels)/2)+9]));
if any(psychrange(pixels) ~= 0) || (pixels(1,1) ~= i)
fprintf(' --> TROUBLE!');
trouble = trouble + 1;
if (pixels(1,1) ~= i)
fprintf(' WRONG VALUE');
else
fprintf(' DITHERING OR CROSS CHANNEL/CROSS ROW MISMATCH:\n');
disp(pixels(:,[1:10, floor(length(pixels)/2):floor(length(pixels)/2)+9]));
end
end
fprintf('\n');
even(i+1) = pixels(1, 1);
odd(i+1) = pixels(1, 2);
if KbCheck(-1)
break;
end
end
if bitssharp
BitsPlusPlus('SwitchToBits++');
BitsPlusPlus('Close');
else
Datapixx('Close');
end
sca;
if trouble > 0
fprintf('\n\nFAILURE! Many wrong pixels detected! Trouble for %i separate levels!!!\n', trouble);
close all;
plot(0:255, even, 'r', 0:255, odd, 'g');
elseif i < 255
fprintf('\n\nEARLY USER ABORT BEFORE ALL 255 SAMPLES taken - INCONCLUSIVE!)\n');
else
fprintf('\n\nALL GOOD :)\n');
end
Screen('Preference', 'SkipSynctests', oldsynclevel);
return;
|