Browse Source

Merge branch '201402_opencl_cleanup' into bfgminer

Luke Dashjr 12 years ago
parent
commit
b69043c88e
12 changed files with 461 additions and 522 deletions
  1. 3 22
      README
  2. 22 25
      README.GPU
  3. 37 73
      README.RPC
  4. 24 24
      README.scrypt
  5. 97 152
      api.c
  6. 4 0
      compat.h
  7. 6 0
      configure.ac
  8. 237 187
      driver-opencl.c
  9. 6 1
      driver-opencl.h
  10. 15 38
      miner.c
  11. 9 0
      ocl.c
  12. 1 0
      ocl.h

+ 3 - 22
README

@@ -299,35 +299,16 @@ GPU only options:
 
 
 --auto-fan          Automatically adjust all GPU fan speeds to maintain a target temperature
 --auto-fan          Automatically adjust all GPU fan speeds to maintain a target temperature
 --auto-gpu          Automatically adjust all GPU engine clock speeds to maintain a target temperature
 --auto-gpu          Automatically adjust all GPU engine clock speeds to maintain a target temperature
---gpu-threads <arg> Number of threads per GPU (1 - 10) - one value for all or separate by commas for per card (default: -1)
 --gpu-dyninterval <arg> Set the refresh interval in ms for GPUs using dynamic intensity (default: 7)
 --gpu-dyninterval <arg> Set the refresh interval in ms for GPUs using dynamic intensity (default: 7)
---gpu-engine <arg>  GPU engine (over)clock range in MHz - one value, range and/or comma separated list (e.g. 850-900,900,750-850)
---gpu-fan <arg>     GPU fan percentage range - one value, range and/or comma separated list (e.g. 25-85,85,65)
 --gpu-map <arg>     Map OpenCL to ADL device order manually, paired CSV (e.g. 1:0,2:1 maps OpenCL 1 to ADL 0, 2 to 1)
 --gpu-map <arg>     Map OpenCL to ADL device order manually, paired CSV (e.g. 1:0,2:1 maps OpenCL 1 to ADL 0, 2 to 1)
---gpu-memclock <arg> Set the GPU memory (over)clock in MHz - one value for all or separate by commas for per card.
---gpu-memdiff <arg> Set a fixed difference in clock speed between the GPU and memory in auto-gpu mode
 --gpu-platform <arg> Select OpenCL platform ID to use for GPU mining
 --gpu-platform <arg> Select OpenCL platform ID to use for GPU mining
---gpu-powertune <arg> Set the GPU powertune percentage - one value for all or separate by commas for per card.
 --gpu-reorder       Attempt to reorder GPU devices according to PCI Bus ID
 --gpu-reorder       Attempt to reorder GPU devices according to PCI Bus ID
---gpu-vddc <arg>    Set the GPU voltage in Volts - one value for all or separate by commas for per card.
---intensity <arg>   Intensity of GPU scanning (d or -10 -> 31,default: d to maintain desktop interactivity)
---kernel <arg>      Override sha256 kernel to use (diablo, poclbm, phatk or diakgcn) - one value or comma separated
 --no-adl            Disable the ATI display library used for monitoring and setting GPU parameters
 --no-adl            Disable the ATI display library used for monitoring and setting GPU parameters
---temp-overheat <arg> Overheat temperature when automatically managing fan and GPU speeds (default: 85)
---vectors <arg>     Override detected optimal vector (1, 2 or 4) - one value or comma separated list
---worksize <arg>    Override detected optimal worksize - one value or comma separated list
 
 
 GPU mining is disabled by default for SHA256d if you have any dedicated mining
 GPU mining is disabled by default for SHA256d if you have any dedicated mining
 devices, but can be enabled explicitly specifying the -S opencl:auto option.
 devices, but can be enabled explicitly specifying the -S opencl:auto option.
 
 
 See README.GPU for more information regarding GPU mining.
 See README.GPU for more information regarding GPU mining.
-
-scrypt only options:
-
---lookup-gap <arg>  Set GPU lookup gap for scrypt mining, comma separated
---shaders <arg>     GPU shaders per card for tuning scrypt, comma separated
---thread-concurrency <arg> Set GPU thread concurrency for scrypt mining, comma separated
-
 See README.scrypt for more information regarding (non-bitcoin) scrypt mining.
 See README.scrypt for more information regarding (non-bitcoin) scrypt mining.
 
 
 
 
@@ -752,9 +733,9 @@ A; Try the --net-delay option if you are on a getwork or GBT server.
 Q: How do I tune for P2Pool?
 Q: How do I tune for P2Pool?
 A: P2Pool has very rapid expiration of work and new blocks, it is suggested you
 A: P2Pool has very rapid expiration of work and new blocks, it is suggested you
 decrease intensity by 1 from your optimal value, and decrease GPU threads to 1
 decrease intensity by 1 from your optimal value, and decrease GPU threads to 1
-with --gpu-threads 1. It is also recommended to use --failover-only since the
-work is effectively like a different block chain. If mining with a Mini Rig, it
-is worth adding the --bfl-range option.
+with --set-device OCL:threads=1. It is also recommended to use --failover-only
+since the work is effectively like a different block chain. If mining with a
+Mini Rig, it is worth adding the --bfl-range option.
 
 
 Q: Are OpenCL kernels from other mining software useable in BFGMiner?
 Q: Are OpenCL kernels from other mining software useable in BFGMiner?
 A: No, the APIs are slightly different between the different software and they
 A: No, the APIs are slightly different between the different software and they

+ 22 - 25
README.GPU

@@ -14,23 +14,23 @@ mining performance.
 
 
 Single pool, dedicated miner:
 Single pool, dedicated miner:
 
 
-bfgminer -S opencl:auto -o http://pool:port -u username -p password --intensity 9
+bfgminer -S opencl:auto -o http://pool:port -u username -p password --set-device intensity=9
 
 
 Single pool, first card regular desktop, 3 other dedicated cards:
 Single pool, first card regular desktop, 3 other dedicated cards:
 
 
-bfgminer -S opencl:auto -o http://pool:port -u username -p password --intensity d,9,9,9
+bfgminer -S opencl:auto -o http://pool:port -u username -p password --set-device intensity=9 --set-device OCL0:intensity=d
 
 
 Multiple pool, dedicated miner:
 Multiple pool, dedicated miner:
 
 
-bfgminer -S opencl:auto -o http://pool1:port -u pool1username -p pool1password -o http://pool2:port -u pool2usernmae -p pool2password --intensity 9
+bfgminer -S opencl:auto -o http://pool1:port -u pool1username -p pool1password -o http://pool2:port -u pool2usernmae -p pool2password --set-device intensity=9
 
 
 Add overclocking settings, GPU and fan control for all cards:
 Add overclocking settings, GPU and fan control for all cards:
 
 
-bfgminer -S opencl:auto -o http://pool:port -u username -p password --intensity 9 --auto-fan --auto-gpu --gpu-engine 750-950 --gpu-memclock 300
+bfgminer -S opencl:auto -o http://pool:port -u username -p password --set-device intensity=9 --auto-fan --auto-gpu --set-device OCL:clock=750-950 --set-device OCL:memclock=300
 
 
 Add overclocking settings, GPU and fan control with different engine settings for 4 cards:
 Add overclocking settings, GPU and fan control with different engine settings for 4 cards:
 
 
-bfgminer -S opencl:auto -o http://pool:port -u username -p password --intensity 9 --auto-fan --auto-gpu --gpu-engine 750-950,945,700-930,960 --gpu-memclock 300
+bfgminer -S opencl:auto -o http://pool:port -u username -p password --set-device intensity=9 --auto-fan --auto-gpu --set-device OCL0:clock=750-950 --set-device OCL1:clock=945 --set-device OCL2:clock=700-930 --set-device OCL3:clock=960 --set-device OCL:memclock=300
 
 
 READ WARNINGS AND DOCUMENTATION BELOW ABOUT OVERCLOCKING
 READ WARNINGS AND DOCUMENTATION BELOW ABOUT OVERCLOCKING
 
 
@@ -114,19 +114,15 @@ specified. All settings can all be changed within the menu on the fly on a
 per-GPU basis.
 per-GPU basis.
 
 
 For example:
 For example:
---gpu-engine 950 --gpu-memclock 825
+--set-device OCL:clock=950 --set-device OCL:memclock=825
 
 
 will try to set all GPU engine clocks to 950 and all memory clocks to 825,
 will try to set all GPU engine clocks to 950 and all memory clocks to 825,
 while:
 while:
---gpu-engine 950,945,930,960 --gpu-memclock 300
+--set-device OCL0:clock=950 --set-device OCL1:clock=945 --set-device OCL2:clock=930 --set-device OCL3:clock=960 --set-device OCL:memclock=300
 
 
 will try to set the engine clock of card 0 to 950, 1 to 945, 2 to 930, 3 to
 will try to set the engine clock of card 0 to 950, 1 to 945, 2 to 930, 3 to
 960 and all memory clocks to 300.
 960 and all memory clocks to 300.
 
 
-You can substitute 0 to leave the engine clock of a card at its default.
-For example, to keep the 2nd GPU to its default clocks:
---gpu-engine 950,0,930,960 --gpu-memclock 300,0,300,300
-
 AUTO MODES:
 AUTO MODES:
 There are two "auto" modes in BFGMiner, --auto-fan and --auto-gpu. These can be
 There are two "auto" modes in BFGMiner, --auto-fan and --auto-gpu. These can be
 used independently of each other and are complementary. Both auto modes are
 used independently of each other and are complementary. Both auto modes are
@@ -143,7 +139,7 @@ Sets card 0 target temperature to 75, and card 1 to 85 degrees.
 AUTO FAN:
 AUTO FAN:
 e.g.
 e.g.
 --auto-fan (implies 85% upper limit)
 --auto-fan (implies 85% upper limit)
---gpu-fan 25-85,65 --auto-fan
+--set-device OCL0:fan=25-85 --set-device OCL1:fan=65 --auto-fan
 
 
 Fan control in auto fan works off the theory that the minimum possible fan
 Fan control in auto fan works off the theory that the minimum possible fan
 required to maintain an optimal temperature will use less power, make less
 required to maintain an optimal temperature will use less power, make less
@@ -152,17 +148,16 @@ limited to 85% if the temperature is below "overheat" intentionally, as higher
 fanspeeds on GPUs do not produce signficantly more cooling, yet significantly
 fanspeeds on GPUs do not produce signficantly more cooling, yet significantly
 shorten the lifespan of the fans. If temperature reaches the overheat value,
 shorten the lifespan of the fans. If temperature reaches the overheat value,
 fanspeed will still be increased to 100%. The overheat value is set to 85
 fanspeed will still be increased to 100%. The overheat value is set to 85
-degrees by default and can be changed with:
+degrees by default and can be changed with the temp_overheat setting:
 
 
---temp-overheat
 e.g.
 e.g.
---temp-overheat 75,85
+--set-device OCL0:temp_overheat=75 --set-device OCL1:temp_overheat=85
 Sets card 0 overheat threshold to 75 degrees and card 1 to 85.
 Sets card 0 overheat threshold to 75 degrees and card 1 to 85.
 
 
 AUTO GPU:
 AUTO GPU:
 e.g.
 e.g.
---auto-gpu --gpu-engine 750-950
---auto-gpu --gpu-engine 750-950,945,700-930,960
+--auto-gpu --set-device OCL:clock=750-950
+--auto-gpu --set-device OCL0:clock=750-950 --set-device OCL1:clock=945 --set-device OCL2:clock=700-930 --set-device OCL3:clock=960
 
 
 GPU control in auto gpu tries to maintain as high a clock speed as possible
 GPU control in auto gpu tries to maintain as high a clock speed as possible
 while not reaching overheat temperatures. As a lower clock speed limit, the
 while not reaching overheat temperatures. As a lower clock speed limit, the
@@ -187,7 +182,7 @@ temperature can be changed with:
 --set-device OCL0:temp-cutoff=95 --set-device OCL1:temp-cutoff=105
 --set-device OCL0:temp-cutoff=95 --set-device OCL1:temp-cutoff=105
 Sets card 0 cutoff temperature to 95 and card 1 to 105.
 Sets card 0 cutoff temperature to 95 and card 1 to 105.
 
 
---gpu-memdiff -125
+--set-device OCL:memdiff=-125
 This setting will modify the memory speed whenever the GPU clock speed is
 This setting will modify the memory speed whenever the GPU clock speed is
 modified by --auto-gpu. In this example, it will set the memory speed to be 125
 modified by --auto-gpu. In this example, it will set the memory speed to be 125
 MHz lower than the GPU speed. This is useful for some cards like the 6970 which
 MHz lower than the GPU speed. This is useful for some cards like the 6970 which
@@ -306,7 +301,9 @@ To work around this you would use:
 GPU FAQ:
 GPU FAQ:
 
 
 Q: Can I change the intensity settings individually for each GPU?
 Q: Can I change the intensity settings individually for each GPU?
-A: Yes, pass a list separated by commas such as --intensity d,4,9,9
+A: Yes, specify the devices by identifier: --set-device intensity=9 --set-device
+OCL0:intensity=d --set-device OCL1:intensity=4 (be sure you set the catch-all
+first!)
 
 
 Q: The CPU usage is high.
 Q: The CPU usage is high.
 A: The ATI drivers after 11.6 have a bug that makes them consume 100% of one
 A: The ATI drivers after 11.6 have a bug that makes them consume 100% of one
@@ -324,12 +321,12 @@ you will be able to run. You are more likely to hit your limits with BFGMiner
 and you will find you may need to overclock your GPU less aggressively. The
 and you will find you may need to overclock your GPU less aggressively. The
 software cannot be responsible and make your GPU hang directly. If you simply
 software cannot be responsible and make your GPU hang directly. If you simply
 cannot get it to ever stop hanging, try decreasing the intensity, and if even
 cannot get it to ever stop hanging, try decreasing the intensity, and if even
-that fails, try changing to the poclbm kernel with --kernel poclbm, though you
-will sacrifice performance. BFGMiner is designed to try and safely restart GPUs
-as much as possible, but NOT if that restart might actually crash the rest of
-the GPUs mining, or even the machine. It tries to restart them with a separate
-thread and if that separate thread dies, it gives up trying to restart any more
-GPUs.
+that fails, try changing to the poclbm kernel with --set-device
+OCL:kernel=poclbm, though you will sacrifice performance. BFGMiner is designed
+to try and safely restart GPUs as much as possible, but NOT if that restart
+might actually crash the rest of the GPUs mining, or even the machine. It tries
+to restart them with a separate thread and if that separate thread dies, it
+gives up trying to restart any more GPUs.
 
 
 Q: Can you change the autofan/autogpu to change speeds in a different manner?
 Q: Can you change the autofan/autogpu to change speeds in a different manner?
 A: The defaults are sane and safe. I'm not interested in changing them further.
 A: The defaults are sane and safe. I'm not interested in changing them further.

+ 37 - 73
README.RPC

@@ -66,11 +66,11 @@ response, otherwise it replies with text formatted as described further below.
 The JSON request format required is '{"command":"CMD","parameter":"PARAM"}'
 The JSON request format required is '{"command":"CMD","parameter":"PARAM"}'
 (though of course parameter is not required for all requests)
 (though of course parameter is not required for all requests)
 where "CMD" is from the "Request" column below and "PARAM" would be e.g.
 where "CMD" is from the "Request" column below and "PARAM" would be e.g.
-the CPU/GPU number if required.
+the device number if required.
 
 
-An example request in both formats to set GPU 0 fan to 80%:
-  gpufan|0,80
-  {"command":"gpufan","parameter":"0,80"}
+An example request in both formats to set device 0 fan to 80%:
+  pgaset|0,fan,80
+  {"command":"pgaset","parameter":"0,fan,80"}
 
 
 The format of each reply (unless stated otherwise) is a STATUS section
 The format of each reply (unless stated otherwise) is a STATUS section
 followed by an optional detail section.
 followed by an optional detail section.
@@ -150,9 +150,7 @@ The list of requests - a (*) means it requires privileged access - and replies:
                               API=API version
                               API=API version
 
 
  config        CONFIG         Some miner configuration information:
  config        CONFIG         Some miner configuration information:
-                              GPU Count=N, <- the number of GPUs
                               PGA Count=N, <- the number of PGAs
                               PGA Count=N, <- the number of PGAs
-                              CPU Count=N, <- the number of CPUs
                               Pool Count=N, <- the number of Pools
                               Pool Count=N, <- the number of Pools
                               ADL=X, <- Y or N if ADL is compiled in the code
                               ADL=X, <- Y or N if ADL is compiled in the code
                               ADL in use=X, <- Y or N if any GPU has ADL
                               ADL in use=X, <- Y or N if any GPU has ADL
@@ -172,15 +170,13 @@ The list of requests - a (*) means it requires privileged access - and replies:
  pools         POOLS          The status of each pool e.g.
  pools         POOLS          The status of each pool e.g.
                               Pool=0,URL=http://pool.com:6311,Status=Alive,...|
                               Pool=0,URL=http://pool.com:6311,Status=Alive,...|
 
 
- devs          DEVS           Each available GPU, PGA and CPU with their status
-                              e.g. GPU=0,Accepted=NN,MHS av=NNN,...,Intensity=D|
+ devs          DEVS           Each available device with their status
+                              e.g. PGA=0,Accepted=NN,MHS av=NNN,...,Intensity=D|
                               Last Share Time=NNN, <- standard long time in sec
                               Last Share Time=NNN, <- standard long time in sec
                                (or 0 if none) of last accepted share
                                (or 0 if none) of last accepted share
                               Last Share Pool=N, <- pool number (or -1 if none)
                               Last Share Pool=N, <- pool number (or -1 if none)
                               Last Valid Work=NNN, <- standand long time in sec
                               Last Valid Work=NNN, <- standand long time in sec
                                of last work returned that wasn't an HW:
                                of last work returned that wasn't an HW:
-                              Will not report PGAs if PGA mining is disabled
-                              Will not report CPUs if CPU mining is disabled
 
 
  procs         DEVS           The details of each processor in the same format
  procs         DEVS           The details of each processor in the same format
                               and details as for DEVS
                               and details as for DEVS
@@ -189,9 +185,6 @@ The list of requests - a (*) means it requires privileged access - and replies:
                               the same format as the --scan-serial command line
                               the same format as the --scan-serial command line
                               option
                               option
 
 
- gpu|N         GPU            The details of a single GPU number N in the same
-                              format and details as for DEVS
-
  pga|N         PGA            The details of a single PGA number N in the same
  pga|N         PGA            The details of a single PGA number N in the same
                               format and details as for DEVS
                               format and details as for DEVS
                               This is only available if PGA mining is enabled
                               This is only available if PGA mining is enabled
@@ -201,21 +194,11 @@ The list of requests - a (*) means it requires privileged access - and replies:
  proc|N        PGA            The details of a single processor number N in the
  proc|N        PGA            The details of a single processor number N in the
                               same format and details as for DEVS
                               same format and details as for DEVS
 
 
- cpu|N         CPU            The details of a single CPU number N in the same
-                              format and details as for DEVS
-                              This is only available if CPU mining is enabled
-                              Use 'cpucount' or 'config' first to see if there are any
-
- gpucount      GPUS           Count=N| <- the number of GPUs
-
  pgacount      PGAS           Count=N| <- the number of PGAs
  pgacount      PGAS           Count=N| <- the number of PGAs
                               Always returns 0 if PGA mining is disabled
                               Always returns 0 if PGA mining is disabled
 
 
  proccount     PGAS           Count=N| <- the number of processors
  proccount     PGAS           Count=N| <- the number of processors
 
 
- cpucount      CPUS           Count=N| <- the number of CPUs
-                              Always returns 0 if CPU mining is disabled
-
  switchpool|N (*)
  switchpool|N (*)
                none           There is no reply section just the STATUS section
                none           There is no reply section just the STATUS section
                               stating the results of switching pool N to the
                               stating the results of switching pool N to the
@@ -254,54 +237,6 @@ The list of requests - a (*) means it requires privileged access - and replies:
                               The Msg includes the pool URL
                               The Msg includes the pool URL
                               N.B. all details for the pool will be lost
                               N.B. all details for the pool will be lost
 
 
- cpuenable|N (*)
-               none           There is no reply section just the STATUS section
-                              stating the results of the enable request
-
- cpudisable|N (*)
-               none           There is no reply section just the STATUS section
-                              stating the results of the disable request
-
- cpurestart|N (*)
-               none           There is no reply section just the STATUS section
-                              stating the results of the restart request
-
- gpuenable|N (*)
-               none           There is no reply section just the STATUS section
-                              stating the results of the enable request
-
- gpudisable|N (*)
-               none           There is no reply section just the STATUS section
-                              stating the results of the disable request
-
- gpurestart|N (*)
-               none           There is no reply section just the STATUS section
-                              stating the results of the restart request
-
- gpuintensity|N,I (*)
-               none           There is no reply section just the STATUS section
-                              stating the results of setting GPU N intensity
-                              to I
-
- gpumem|N,V (*)
-               none           There is no reply section just the STATUS section
-                              stating the results of setting GPU N memoryclock
-                              to V MHz
-
- gpuengine|N,V (*)
-               none           There is no reply section just the STATUS section
-                              stating the results of setting GPU N clock
-                              to V MHz
-
- gpufan|N,V (*)
-               none           There is no reply section just the STATUS section
-                              stating the results of setting GPU N fan speed
-                              to V%
-
- gpuvddc|N,V (*)
-               none           There is no reply section just the STATUS section
-                              stating the results of setting GPU N vddc to V
-
  save|filename (*)
  save|filename (*)
                none           There is no reply section just the STATUS section
                none           There is no reply section just the STATUS section
                               stating success or failure saving the BFGMiner
                               stating success or failure saving the BFGMiner
@@ -334,6 +269,10 @@ The list of requests - a (*) means it requires privileged access - and replies:
                               stating the results of the disable request
                               stating the results of the disable request
                               This is only available if PGA mining is enabled
                               This is only available if PGA mining is enabled
 
 
+ pgarestart|N (*)
+               none           There is no reply section just the STATUS section
+                              stating the results of the restart request
+
  pgaidentify|N (*)
  pgaidentify|N (*)
                none           This is equivalent to PROCIDENTIFY on the first
                none           This is equivalent to PROCIDENTIFY on the first
                               processor of any given device
                               processor of any given device
@@ -452,8 +391,8 @@ The list of requests - a (*) means it requires privileged access - and replies:
                               is shown on the BFGMiner display like is normally
                               is shown on the BFGMiner display like is normally
                               displayed on exit.
                               displayed on exit.
 
 
-When you enable, disable or restart a GPU or PGA, you will also get Thread
-messages in the BFGMiner status window.
+When you enable, disable or restart a device, you will also get Thread messages
+in the BFGMiner status window.
 
 
 The 'poolpriority' command can be used to reset the priority order of multiple
 The 'poolpriority' command can be used to reset the priority order of multiple
 pools with a single command - 'switchpool' only sets a single pool to first
 pools with a single command - 'switchpool' only sets a single pool to first
@@ -505,6 +444,31 @@ API V3.1
 
 
 Multiple report request command with '+' e.g. summary+devs
 Multiple report request command with '+' e.g. summary+devs
 
 
+CPU and OpenCL devices are now included as "PGAs", to enable migration to a simpler interface.
+
+Added API commands:
+ 'pgarestart'
+
+Modified API command:
+ 'devs' - remove 'GPU Count' and 'CPU Count'
+
+Deprecated API commands:
+ 'cpu'
+ 'cpucount'
+ 'cpuenable'
+ 'cpudisable'
+ 'cpurestart'
+ 'gpu'
+ 'gpucount'
+ 'gpuenable'
+ 'gpudisable'
+ 'gpurestart'
+ 'gpuintensity'
+ 'gpumem'
+ 'gpuengine'
+ 'gpufan'
+ 'gpuvddc'
+
 ---------
 ---------
 
 
 API V2.3 (BFGMiner v3.7.0)
 API V2.3 (BFGMiner v3.7.0)

+ 24 - 24
README.scrypt

@@ -40,7 +40,7 @@ lines are in the .bat before starting BFGMiner:
 setx GPU_MAX_ALLOC_PERCENT 100
 setx GPU_MAX_ALLOC_PERCENT 100
 setx GPU_USE_SYNC_OBJECTS 1
 setx GPU_USE_SYNC_OBJECTS 1
 
 
---intensity XX
+intensity=XX
 
 
 Just like in Bitcoin mining, scrypt mining takes an intensity, however the
 Just like in Bitcoin mining, scrypt mining takes an intensity, however the
 scale goes from 0 to 31. 
 scale goes from 0 to 31. 
@@ -54,7 +54,7 @@ to a running desktop and performance WILL be poor. The lower limit to intensity
 with scrypt is usually 8 and BFGMiner will prevent it going too low.
 with scrypt is usually 8 and BFGMiner will prevent it going too low.
 SUMMARY: Setting this for reasonable hashrates is mandatory.
 SUMMARY: Setting this for reasonable hashrates is mandatory.
 
 
---shaders XXX
+shaders=XXX
 
 
 is a new option where you tell BFGMiner how many shaders your GPU has. This
 is a new option where you tell BFGMiner how many shaders your GPU has. This
 helps BFGMiner try to choose some meaningful baseline parameters. Use this table
 helps BFGMiner try to choose some meaningful baseline parameters. Use this table
@@ -99,41 +99,40 @@ all you will need to set.
 
 
 
 
 Optional parameters to tune:
 Optional parameters to tune:
---gpu-threads, --thread-concurrency, --lookup-gap
+threads, thread-concurrency, lookup-gap
 
 
---thread-concurrency:
+thread-concurrency:
 This tunes the optimal size of work that scrypt can do. It is internally tuned
 This tunes the optimal size of work that scrypt can do. It is internally tuned
 by BFGMiner to be the highest reasonable multiple of shaders that it can
 by BFGMiner to be the highest reasonable multiple of shaders that it can
 allocate on your GPU. Ideally it should be a multiple of your shader count.
 allocate on your GPU. Ideally it should be a multiple of your shader count.
 vliw5 architecture (R5XXX) would be best at 5x shaders, while VLIW4 (R6xxx and
 vliw5 architecture (R5XXX) would be best at 5x shaders, while VLIW4 (R6xxx and
 R7xxx) are best at 4x. Setting thread concurrency overrides anything you put
 R7xxx) are best at 4x. Setting thread concurrency overrides anything you put
-into --shaders and is ultimately a BETTER way to tune performance.
+into the shaders config and is ultimately a BETTER way to tune performance.
 SUMMARY: Spend lots of time finding the highest value that your device likes
 SUMMARY: Spend lots of time finding the highest value that your device likes
 and increases hashrate.
 and increases hashrate.
 
 
---gpu-threads:
+threads:
 Once you have found the optimal shaders and intensity, you can start increasing
 Once you have found the optimal shaders and intensity, you can start increasing
-the --gpu-threads value till BFGMiner fails to start. This is really only of
-value if you want to run low intensities as you will be unable to run more than
-1.
+the threads value till BFGMiner fails to start. This is really only of value if
+you want to run low intensities as you will be unable to run more than 1.
 SUMMARY: Don't touch this.
 SUMMARY: Don't touch this.
 
 
---lookup-gap
+lookup-gap:
 This tunes a compromise between ram usage and performance. Performance peaks
 This tunes a compromise between ram usage and performance. Performance peaks
 at a gap of 2, but increasing the gap can save you some GPU ram, but almost
 at a gap of 2, but increasing the gap can save you some GPU ram, but almost
 always at the cost of significant loss of hashrate. Setting lookup gap
 always at the cost of significant loss of hashrate. Setting lookup gap
-overrides the default of 2, but BFGMiner will use the --shaders value to choose
-a thread-concurrency if you haven't chosen one.
+overrides the default of 2, but BFGMiner will use the provided shaders value to
+choose a thread-concurrency if you haven't chosen one.
 SUMMARY: Don't touch this.
 SUMMARY: Don't touch this.
 
 
 
 
 Related parameters:
 Related parameters:
---worksize XX
+work_size=XX
 Has a minor effect, should be a multiple of 64 up to 256 maximum.
 Has a minor effect, should be a multiple of 64 up to 256 maximum.
 SUMMARY: Worth playing with once everything else has been tried but will
 SUMMARY: Worth playing with once everything else has been tried but will
 probably do nothing.
 probably do nothing.
 
 
---vectors XX
+vectors=XX
 Vectors are NOT used by the scrypt mining kernel.
 Vectors are NOT used by the scrypt mining kernel.
 SUMMARY: Does nothing.
 SUMMARY: Does nothing.
 
 
@@ -157,7 +156,8 @@ required for scrypt mining, and 4GB is suggested.
 Finally, the power consumption while mining at high engine clocks, very high
 Finally, the power consumption while mining at high engine clocks, very high
 memory clocks can be far in excess of what you might imagine.
 memory clocks can be far in excess of what you might imagine.
 For example, a 7970 running with the following settings:
 For example, a 7970 running with the following settings:
---thread-concurrency 22392 --gpu-engine 1135 --gpu-memclock 1890
+--set-device OCL:thread-concurrency=22392 --set-device OCL:clock=1135
+--set-device OCL:memclock=1890
 was using 305W!
 was using 305W!
 
 
 ---
 ---
@@ -181,7 +181,7 @@ generated.
 
 
 First try without any thread concurrency or even shaders, as BFGMiner will try to
 First try without any thread concurrency or even shaders, as BFGMiner will try to
 find an optimal value:
 find an optimal value:
-bfgminer --intensity 13
+bfgminer --set-device OCL:intensity=13
 
 
 If that starts mining, see what bin was generated, it is likely the largest
 If that starts mining, see what bin was generated, it is likely the largest
 meaningful TC you can set.
 meaningful TC you can set.
@@ -190,13 +190,13 @@ scrypt130302Tahitiglg2tc22392w64l8.bin
 
 
 Note that tc22392 tells you what thread concurrency it was. It should start
 Note that tc22392 tells you what thread concurrency it was. It should start
 without TC parameters, but you never know. So if it doesn't, start with
 without TC parameters, but you never know. So if it doesn't, start with
---thread-concurrency 8192 and add 2048 to it at a time till you find the highest
-value it will start successfully at.
+--set-device OCL:thread-concurrency=8192 and add 2048 to it at a time till you
+find the highest value it will start successfully at.
 
 
 If you wish to get a little extra from your hardware, you may also try
 If you wish to get a little extra from your hardware, you may also try
 overclocking. Do note that this will damage your GPUs and void your warranty,
 overclocking. Do note that this will damage your GPUs and void your warranty,
-so unless you are willing to take that risk, skip the --gpu-engine and
---gpu-memclock sections!
+so unless you are willing to take that risk, skip the clock and memclock
+parameters!
 
 
 Then start overclocking the eyeballs off your memory, as 7970s are exquisitely
 Then start overclocking the eyeballs off your memory, as 7970s are exquisitely
 sensitive to memory speed and amazingly overclockable but please make sure it
 sensitive to memory speed and amazingly overclockable but please make sure it
@@ -217,14 +217,14 @@ without crashing the GPU, you will have to use a lower memclock.
 Then, and only then, bother trying to increase intensity further.
 Then, and only then, bother trying to increase intensity further.
 
 
 My final settings were:
 My final settings were:
---gpu-engine 1141  --gpu-memclock 1875 --intensity 20
+--set-device OCL:clock=1141 --set-device OCL:memclock=1875 --set-device OCL:intensity=20
 for a hashrate of 745kH.
 for a hashrate of 745kH.
 
 
 Note I did not bother setting a thread concurrency. Once you have the magic
 Note I did not bother setting a thread concurrency. Once you have the magic
 endpoint, look at what tc was chosen by the bin file generated and then hard
 endpoint, look at what tc was chosen by the bin file generated and then hard
-code that in next time (eg --thread-concurrency 22392) as slight changes in
-thread concurrency will happen every time if you don't specify one, and the tc
-to clock ratios are critical!
+code that in next time (eg --set-device OCL:thread-concurrency=22392) as slight
+changes in thread concurrency will happen every time if you don't specify one,
+and the tc to clock ratios are critical!
 
 
 Your numbers will be your numbers depending on your hardware combination and OS,
 Your numbers will be your numbers depending on your hardware combination and OS,
 so don't expect to get exactly the same results!
 so don't expect to get exactly the same results!

+ 97 - 152
api.c

@@ -264,6 +264,7 @@ static const char *JSON_PARAMETER = "parameter";
 #define MSG_PGALRDIS 62
 #define MSG_PGALRDIS 62
 #define MSG_PGAENA 63
 #define MSG_PGAENA 63
 #define MSG_PGADIS 64
 #define MSG_PGADIS 64
+#define MSG_PGAREI 0x101
 #define MSG_PGAUNW 65
 #define MSG_PGAUNW 65
 #endif
 #endif
 
 
@@ -535,14 +536,6 @@ struct APIGROUPS {
 static struct IP4ACCESS *ipaccess = NULL;
 static struct IP4ACCESS *ipaccess = NULL;
 static int ips = 0;
 static int ips = 0;
 
 
-#ifdef HAVE_OPENCL
-extern struct device_drv opencl_api;
-#endif
-
-#ifdef WANT_CPUMINE
-extern struct device_drv cpu_drv;
-#endif
-
 struct io_data {
 struct io_data {
 	bytes_t data;
 	bytes_t data;
 	SOCKETTYPE sock;
 	SOCKETTYPE sock;
@@ -1110,14 +1103,6 @@ static int numpgas()
 
 
 	rd_lock(&devices_lock);
 	rd_lock(&devices_lock);
 	for (i = 0; i < total_devices; i++) {
 	for (i = 0; i < total_devices; i++) {
-#ifdef HAVE_OPENCL
-		if (devices[i]->drv == &opencl_api)
-			continue;
-#endif
-#ifdef WANT_CPUMINE
-		if (devices[i]->drv == &cpu_drv)
-			continue;
-#endif
 		if (devices[i]->device != devices[i] && !per_proc)
 		if (devices[i]->device != devices[i] && !per_proc)
 			continue;
 			continue;
 		++count;
 		++count;
@@ -1133,14 +1118,6 @@ static int pgadevice(int pgaid)
 
 
 	rd_lock(&devices_lock);
 	rd_lock(&devices_lock);
 	for (i = 0; i < total_devices; i++) {
 	for (i = 0; i < total_devices; i++) {
-#ifdef HAVE_OPENCL
-		if (devices[i]->drv == &opencl_api)
-			continue;
-#endif
-#ifdef WANT_CPUMINE
-		if (devices[i]->drv == &cpu_drv)
-			continue;
-#endif
 		if (devices[i]->device != devices[i] && !per_proc)
 		if (devices[i]->device != devices[i] && !per_proc)
 			continue;
 			continue;
 		++count;
 		++count;
@@ -1330,9 +1307,7 @@ static void minerconfig(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __
 	char buf[TMPBUFSIZ];
 	char buf[TMPBUFSIZ];
 	bool io_open;
 	bool io_open;
 	struct driver_registration *reg, *regtmp;
 	struct driver_registration *reg, *regtmp;
-	int gpucount = 0;
 	int pgacount = 0;
 	int pgacount = 0;
-	int cpucount = 0;
 	char *adlinuse = (char *)NO;
 	char *adlinuse = (char *)NO;
 #ifdef HAVE_ADL
 #ifdef HAVE_ADL
 	const char *adl = YES;
 	const char *adl = YES;
@@ -1349,24 +1324,14 @@ static void minerconfig(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __
 	const char *adl = NO;
 	const char *adl = NO;
 #endif
 #endif
 
 
-#ifdef HAVE_OPENCL
-	gpucount = nDevs;
-#endif
-
 #ifdef HAVE_AN_FPGA
 #ifdef HAVE_AN_FPGA
 	pgacount = numpgas();
 	pgacount = numpgas();
 #endif
 #endif
 
 
-#ifdef WANT_CPUMINE
-	cpucount = opt_n_threads > 0 ? num_processors : 0;
-#endif
-
 	message(io_data, MSG_MINECONFIG, 0, NULL, isjson);
 	message(io_data, MSG_MINECONFIG, 0, NULL, isjson);
 	io_open = io_add(io_data, isjson ? COMSTR JSON_MINECONFIG : _MINECONFIG COMSTR);
 	io_open = io_add(io_data, isjson ? COMSTR JSON_MINECONFIG : _MINECONFIG COMSTR);
 
 
-	root = api_add_int(root, "GPU Count", &gpucount, false);
 	root = api_add_int(root, "PGA Count", &pgacount, false);
 	root = api_add_int(root, "PGA Count", &pgacount, false);
-	root = api_add_int(root, "CPU Count", &cpucount, false);
 	root = api_add_int(root, "Pool Count", &total_pools, false);
 	root = api_add_int(root, "Pool Count", &total_pools, false);
 	root = api_add_const(root, "ADL", (char *)adl, false);
 	root = api_add_const(root, "ADL", (char *)adl, false);
 	root = api_add_string(root, "ADL in use", adlinuse, false);
 	root = api_add_string(root, "ADL in use", adlinuse, false);
@@ -1729,28 +1694,44 @@ static void devscan(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __mayb
 }
 }
 
 
 #ifdef HAVE_AN_FPGA
 #ifdef HAVE_AN_FPGA
-static void pgadev(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
+static
+struct cgpu_info *get_pga_cgpu(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group, int *id_p, int *dev_p)
 {
 {
-	bool io_open = false;
 	int numpga = numpgas();
 	int numpga = numpgas();
-	int id;
-
+	
 	if (numpga == 0) {
 	if (numpga == 0) {
 		message(io_data, MSG_PGANON, 0, NULL, isjson);
 		message(io_data, MSG_PGANON, 0, NULL, isjson);
-		return;
+		return NULL;
 	}
 	}
-
+	
 	if (param == NULL || *param == '\0') {
 	if (param == NULL || *param == '\0') {
 		message(io_data, MSG_MISID, 0, NULL, isjson);
 		message(io_data, MSG_MISID, 0, NULL, isjson);
-		return;
+		return NULL;
 	}
 	}
-
-	id = atoi(param);
-	if (id < 0 || id >= numpga) {
-		message(io_data, MSG_INVPGA, id, NULL, isjson);
-		return;
+	
+	*id_p = atoi(param);
+	if (*id_p < 0 || *id_p >= numpga) {
+		message(io_data, MSG_INVPGA, *id_p, NULL, isjson);
+		return NULL;
+	}
+	
+	*dev_p = pgadevice(*id_p);
+	if (*dev_p < 0) { // Should never happen
+		message(io_data, MSG_INVPGA, *id_p, NULL, isjson);
+		return NULL;
 	}
 	}
+	
+	return get_devices(*dev_p);
+}
 
 
+static void pgadev(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
+{
+	bool io_open = false;
+	int id, dev;
+
+	if (!get_pga_cgpu(io_data, c, param, isjson, group, &id, &dev))
+		return;
+	
 	message(io_data, MSG_PGADEV, id, NULL, isjson);
 	message(io_data, MSG_PGADEV, id, NULL, isjson);
 
 
 	if (isjson)
 	if (isjson)
@@ -1765,34 +1746,13 @@ static void pgadev(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *p
 static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
 static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
 {
 {
 	struct cgpu_info *cgpu, *proc;
 	struct cgpu_info *cgpu, *proc;
-	int numpga = numpgas();
-	int id;
+	int id, dev;
 	bool already;
 	bool already;
 
 
-	if (numpga == 0) {
-		message(io_data, MSG_PGANON, 0, NULL, isjson);
-		return;
-	}
-
-	if (param == NULL || *param == '\0') {
-		message(io_data, MSG_MISID, 0, NULL, isjson);
+	cgpu = get_pga_cgpu(io_data, c, param, isjson, group, &id, &dev);
+	if (!cgpu)
 		return;
 		return;
-	}
-
-	id = atoi(param);
-	if (id < 0 || id >= numpga) {
-		message(io_data, MSG_INVPGA, id, NULL, isjson);
-		return;
-	}
-
-	int dev = pgadevice(id);
-	if (dev < 0) { // Should never happen
-		message(io_data, MSG_INVPGA, id, NULL, isjson);
-		return;
-	}
-
-	cgpu = get_devices(dev);
-
+	
 	applog(LOG_DEBUG, "API: request to pgaenable %s id %d device %d %s",
 	applog(LOG_DEBUG, "API: request to pgaenable %s id %d device %d %s",
 			per_proc ? "proc" : "dev", id, dev, cgpu->proc_repr_ns);
 			per_proc ? "proc" : "dev", id, dev, cgpu->proc_repr_ns);
 
 
@@ -1826,34 +1786,13 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char
 static void pgadisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
 static void pgadisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
 {
 {
 	struct cgpu_info *cgpu, *proc;
 	struct cgpu_info *cgpu, *proc;
-	int numpga = numpgas();
-	int id;
+	int id, dev;
 	bool already;
 	bool already;
 
 
-	if (numpga == 0) {
-		message(io_data, MSG_PGANON, 0, NULL, isjson);
+	cgpu = get_pga_cgpu(io_data, c, param, isjson, group, &id, &dev);
+	if (!cgpu)
 		return;
 		return;
-	}
-
-	if (param == NULL || *param == '\0') {
-		message(io_data, MSG_MISID, 0, NULL, isjson);
-		return;
-	}
-
-	id = atoi(param);
-	if (id < 0 || id >= numpga) {
-		message(io_data, MSG_INVPGA, id, NULL, isjson);
-		return;
-	}
-
-	int dev = pgadevice(id);
-	if (dev < 0) { // Should never happen
-		message(io_data, MSG_INVPGA, id, NULL, isjson);
-		return;
-	}
-
-	cgpu = get_devices(dev);
-
+	
 	applog(LOG_DEBUG, "API: request to pgadisable %s id %d device %d %s",
 	applog(LOG_DEBUG, "API: request to pgadisable %s id %d device %d %s",
 			per_proc ? "proc" : "dev", id, dev, cgpu->proc_repr_ns);
 			per_proc ? "proc" : "dev", id, dev, cgpu->proc_repr_ns);
 
 
@@ -1877,36 +1816,33 @@ static void pgadisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha
 	message(io_data, MSG_PGADIS, id, NULL, isjson);
 	message(io_data, MSG_PGADIS, id, NULL, isjson);
 }
 }
 
 
-static void pgaidentify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
+static void pgarestart(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
 {
 {
 	struct cgpu_info *cgpu;
 	struct cgpu_info *cgpu;
-	struct device_drv *drv;
-	int numpga = numpgas();
-	int id;
-
-	if (numpga == 0) {
-		message(io_data, MSG_PGANON, 0, NULL, isjson);
-		return;
-	}
-
-	if (param == NULL || *param == '\0') {
-		message(io_data, MSG_MISID, 0, NULL, isjson);
+	int id, dev;
+	
+	cgpu = get_pga_cgpu(io_data, c, param, isjson, group, &id, &dev);
+	if (!cgpu)
 		return;
 		return;
-	}
+	
+	applog(LOG_DEBUG, "API: request to pgarestart dev id %d device %d %s",
+			id, dev, cgpu->dev_repr);
+	
+	reinit_device(cgpu);
+	
+	message(io_data, MSG_PGAREI, id, NULL, isjson);
+}
 
 
-	id = atoi(param);
-	if (id < 0 || id >= numpga) {
-		message(io_data, MSG_INVPGA, id, NULL, isjson);
-		return;
-	}
+static void pgaidentify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
+{
+	struct cgpu_info *cgpu;
+	struct device_drv *drv;
+	int id, dev;
 
 
-	int dev = pgadevice(id);
-	if (dev < 0) { // Should never happen
-		message(io_data, MSG_INVPGA, id, NULL, isjson);
+	cgpu = get_pga_cgpu(io_data, c, param, isjson, group, &id, &dev);
+	if (!cgpu)
 		return;
 		return;
-	}
-
-	cgpu = get_devices(dev);
+	
 	drv = cgpu->drv;
 	drv = cgpu->drv;
 
 
 	if (drv->identify_device && drv->identify_device(cgpu))
 	if (drv->identify_device && drv->identify_device(cgpu))
@@ -2727,28 +2663,28 @@ static void gpuintensity(struct io_data *io_data, __maybe_unused SOCKETTYPE c, c
 {
 {
 	int id;
 	int id;
 	char *value;
 	char *value;
-	int intensity;
 	char intensitystr[7];
 	char intensitystr[7];
+	char buf[TMPBUFSIZ];
 
 
 	if (!splitgpuvalue(io_data, param, &id, &value, isjson))
 	if (!splitgpuvalue(io_data, param, &id, &value, isjson))
 		return;
 		return;
 
 
+	struct cgpu_info * const cgpu = &gpus[id];
 	struct opencl_device_data * const data = gpus[id].device_data;
 	struct opencl_device_data * const data = gpus[id].device_data;
 	
 	
-	if (!strncasecmp(value, DYNAMIC, 1)) {
-		data->dynamic = true;
-		strcpy(intensitystr, DYNAMIC);
+	enum bfg_set_device_replytype success;
+	proc_set_device(cgpu, "intensity", value, buf, &success);
+	if (success == SDR_OK)
+	{
+		if (data->dynamic)
+			strcpy(intensitystr, DYNAMIC);
+		else
+			snprintf(intensitystr, sizeof(intensitystr), "%g", oclthreads_to_intensity(data->oclthreads, !opt_scrypt));
 	}
 	}
-	else {
-		intensity = atoi(value);
-		if (intensity < MIN_INTENSITY || intensity > MAX_INTENSITY) {
-			message(io_data, MSG_INVINT, 0, value, isjson);
-			return;
-		}
-
-		data->dynamic = false;
-		data->intensity = intensity;
-		sprintf(intensitystr, "%d", intensity);
+	else
+	{
+		message(io_data, MSG_INVINT, 0, value, isjson);
+		return;
 	}
 	}
 
 
 	message(io_data, MSG_GPUINT, id, intensitystr, isjson);
 	message(io_data, MSG_GPUINT, id, intensitystr, isjson);
@@ -2759,14 +2695,16 @@ static void gpumem(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe
 #ifdef HAVE_ADL
 #ifdef HAVE_ADL
 	int id;
 	int id;
 	char *value;
 	char *value;
-	int clock;
+	char buf[TMPBUFSIZ];
 
 
 	if (!splitgpuvalue(io_data, param, &id, &value, isjson))
 	if (!splitgpuvalue(io_data, param, &id, &value, isjson))
 		return;
 		return;
 
 
-	clock = atoi(value);
-
-	if (set_memoryclock(id, clock))
+	struct cgpu_info * const cgpu = &gpus[id];
+	
+	enum bfg_set_device_replytype success;
+	proc_set_device(cgpu, "memclock", value, buf, &success);
+	if (success != SDR_OK)
 		message(io_data, MSG_GPUMERR, id, value, isjson);
 		message(io_data, MSG_GPUMERR, id, value, isjson);
 	else
 	else
 		message(io_data, MSG_GPUMEM, id, value, isjson);
 		message(io_data, MSG_GPUMEM, id, value, isjson);
@@ -2780,14 +2718,16 @@ static void gpuengine(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __ma
 #ifdef HAVE_ADL
 #ifdef HAVE_ADL
 	int id;
 	int id;
 	char *value;
 	char *value;
-	int clock;
+	char buf[TMPBUFSIZ];
 
 
 	if (!splitgpuvalue(io_data, param, &id, &value, isjson))
 	if (!splitgpuvalue(io_data, param, &id, &value, isjson))
 		return;
 		return;
 
 
-	clock = atoi(value);
-
-	if (set_engineclock(id, clock))
+	struct cgpu_info * const cgpu = &gpus[id];
+	
+	enum bfg_set_device_replytype success;
+	proc_set_device(cgpu, "clock", value, buf, &success);
+	if (success != SDR_OK)
 		message(io_data, MSG_GPUEERR, id, value, isjson);
 		message(io_data, MSG_GPUEERR, id, value, isjson);
 	else
 	else
 		message(io_data, MSG_GPUENG, id, value, isjson);
 		message(io_data, MSG_GPUENG, id, value, isjson);
@@ -2801,14 +2741,16 @@ static void gpufan(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe
 #ifdef HAVE_ADL
 #ifdef HAVE_ADL
 	int id;
 	int id;
 	char *value;
 	char *value;
-	int fan;
+	char buf[TMPBUFSIZ];
 
 
 	if (!splitgpuvalue(io_data, param, &id, &value, isjson))
 	if (!splitgpuvalue(io_data, param, &id, &value, isjson))
 		return;
 		return;
 
 
-	fan = atoi(value);
-
-	if (set_fanspeed(id, fan))
+	struct cgpu_info * const cgpu = &gpus[id];
+	
+	enum bfg_set_device_replytype success;
+	proc_set_device(cgpu, "fan", value, buf, &success);
+	if (success != SDR_OK)
 		message(io_data, MSG_GPUFERR, id, value, isjson);
 		message(io_data, MSG_GPUFERR, id, value, isjson);
 	else
 	else
 		message(io_data, MSG_GPUFAN, id, value, isjson);
 		message(io_data, MSG_GPUFAN, id, value, isjson);
@@ -2822,14 +2764,16 @@ static void gpuvddc(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __mayb
 #ifdef HAVE_ADL
 #ifdef HAVE_ADL
 	int id;
 	int id;
 	char *value;
 	char *value;
-	float vddc;
+	char buf[TMPBUFSIZ];
 
 
 	if (!splitgpuvalue(io_data, param, &id, &value, isjson))
 	if (!splitgpuvalue(io_data, param, &id, &value, isjson))
 		return;
 		return;
 
 
-	vddc = atof(value);
-
-	if (set_vddc(id, vddc))
+	struct cgpu_info * const cgpu = &gpus[id];
+	
+	enum bfg_set_device_replytype success;
+	proc_set_device(cgpu, "voltage", value, buf, &success);
+	if (success != SDR_OK)
 		message(io_data, MSG_GPUVERR, id, value, isjson);
 		message(io_data, MSG_GPUVERR, id, value, isjson);
 	else
 	else
 		message(io_data, MSG_GPUVDDC, id, value, isjson);
 		message(io_data, MSG_GPUVDDC, id, value, isjson);
@@ -3446,6 +3390,7 @@ struct CMDS {
 	{ "pga",		pgadev,		false,	false },
 	{ "pga",		pgadev,		false,	false },
 	{ "pgaenable",		pgaenable,	true,	false },
 	{ "pgaenable",		pgaenable,	true,	false },
 	{ "pgadisable",		pgadisable,	true,	false },
 	{ "pgadisable",		pgadisable,	true,	false },
+	{ "pgarestart",		pgarestart,	true,	false },
 	{ "pgaidentify",	pgaidentify,	true,	false },
 	{ "pgaidentify",	pgaidentify,	true,	false },
 	{ "proc",		pgadev,		false,	false },
 	{ "proc",		pgadev,		false,	false },
 	{ "procenable",		pgaenable,	true,	false },
 	{ "procenable",		pgaenable,	true,	false },

+ 4 - 0
compat.h

@@ -185,6 +185,10 @@ typedef long suseconds_t;
 
 
 #endif /* WIN32 */
 #endif /* WIN32 */
 
 
+#ifndef HAVE_LOG2
+#	define log2(n)  (log(n) / log(2))
+#endif
+
 #ifndef HAVE_PTHREAD_CANCEL
 #ifndef HAVE_PTHREAD_CANCEL
 
 
 // Bionic (Android) is intentionally missing pthread_cancel, so it is implemented using pthread_kill (handled in util.c)
 // Bionic (Android) is intentionally missing pthread_cancel, so it is implemented using pthread_kill (handled in util.c)

+ 6 - 0
configure.ac

@@ -1551,6 +1551,12 @@ AC_TRY_COMPILE([
 ])
 ])
 
 
 
 
+save_LIBS="$LIBS"
+LIBS="$LIBS $MATH_LIBS"
+AC_CHECK_FUNCS([log2])
+LIBS="$save_LIBS"
+
+
 if test "x$prefix" = xNONE; then
 if test "x$prefix" = xNONE; then
 	prefix=/usr/local
 	prefix=/usr/local
 fi
 fi

+ 237 - 187
driver-opencl.c

@@ -22,6 +22,8 @@
 #include <windows.h>
 #include <windows.h>
 #endif
 #endif
 
 
+#include <ctype.h>
+#include <math.h>
 #include <string.h>
 #include <string.h>
 #include <stdbool.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdint.h>
@@ -270,6 +272,7 @@ extern char *opt_kernel_path;
 extern int gpur_thr_id;
 extern int gpur_thr_id;
 extern bool opt_noadl;
 extern bool opt_noadl;
 extern bool have_opencl;
 extern bool have_opencl;
+static _clState *clStates[MAX_GPUDEVICES];
 
 
 
 
 
 
@@ -326,6 +329,16 @@ const char *_set_list(char * const arg, const char * const emsg, bool (*set_func
 	return NULL;
 	return NULL;
 }
 }
 
 
+#define _SET_INTERFACE(PNAME)  \
+static  \
+const char *opencl_init_ ## PNAME (struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const out_success)  \
+{  \
+	if (!_set_ ## PNAME (proc, newvalue))  \
+		return "Invalid value for " #PNAME;  \
+	return NULL;  \
+}  \
+// END OF _SET_INTERFACE
+
 #define _SET_INT_LIST2(PNAME, VCHECK, FIELD)  \
 #define _SET_INT_LIST2(PNAME, VCHECK, FIELD)  \
 static  \
 static  \
 bool _set_ ## PNAME (struct cgpu_info * const cgpu, const char * const _val)  \
 bool _set_ ## PNAME (struct cgpu_info * const cgpu, const char * const _val)  \
@@ -336,6 +349,7 @@ bool _set_ ## PNAME (struct cgpu_info * const cgpu, const char * const _val)  \
 	FIELD = v;  \
 	FIELD = v;  \
 	return true;  \
 	return true;  \
 }  \
 }  \
+_SET_INTERFACE(PNAME)  \
 const char *set_ ## PNAME(char *arg)  \
 const char *set_ ## PNAME(char *arg)  \
 {  \
 {  \
 	return _set_list(arg, "Invalid value passed to " #PNAME, _set_ ## PNAME);  \
 	return _set_list(arg, "Invalid value passed to " #PNAME, _set_ ## PNAME);  \
@@ -383,6 +397,7 @@ bool _set_kernel(struct cgpu_info * const cgpu, const char * const _val)
 	data->kernel = kern;
 	data->kernel = kern;
 	return true;
 	return true;
 }
 }
+_SET_INTERFACE(kernel)
 const char *set_kernel(char *arg)
 const char *set_kernel(char *arg)
 {
 {
 	if (opt_scrypt)
 	if (opt_scrypt)
@@ -394,6 +409,15 @@ const char *set_kernel(char *arg)
 #ifdef HAVE_ADL
 #ifdef HAVE_ADL
 /* This function allows us to map an adl device to an opencl device for when
 /* This function allows us to map an adl device to an opencl device for when
  * simple enumeration has failed to match them. */
  * simple enumeration has failed to match them. */
+static
+const char *opencl_init_gpu_map(struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const out_success)
+{
+	struct opencl_device_data * const data = proc->device_data;
+	data->virtual_adl = atoi(newvalue);
+	data->mapped = true;
+	return NULL;
+}
+
 char *set_gpu_map(char *arg)
 char *set_gpu_map(char *arg)
 {
 {
 	struct opencl_device_data *data;
 	struct opencl_device_data *data;
@@ -437,10 +461,18 @@ bool _set_gpu_engine(struct cgpu_info * const cgpu, const char * const _val)
 	data->gpu_engine = val2;
 	data->gpu_engine = val2;
 	return true;
 	return true;
 }
 }
+_SET_INTERFACE(gpu_engine)
 const char *set_gpu_engine(char *arg)
 const char *set_gpu_engine(char *arg)
 {
 {
 	return _set_list(arg, "Invalid value passed to set_gpu_engine", _set_gpu_engine);
 	return _set_list(arg, "Invalid value passed to set_gpu_engine", _set_gpu_engine);
 }
 }
+static
+const char *opencl_set_gpu_engine(struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const out_success)
+{
+	if (set_engineclock(proc->device_id, atoi(newvalue)))
+		return "Failed to set gpu_engine";
+	return NULL;
+}
 
 
 static
 static
 bool _set_gpu_fan(struct cgpu_info * const cgpu, const char * const _val)
 bool _set_gpu_fan(struct cgpu_info * const cgpu, const char * const _val)
@@ -454,35 +486,124 @@ bool _set_gpu_fan(struct cgpu_info * const cgpu, const char * const _val)
 	data->gpu_fan = val2;
 	data->gpu_fan = val2;
 	return true;
 	return true;
 }
 }
+_SET_INTERFACE(gpu_fan)
 const char *set_gpu_fan(char *arg)
 const char *set_gpu_fan(char *arg)
 {
 {
 	return _set_list(arg, "Invalid value passed to set_gpu_fan", _set_gpu_fan);
 	return _set_list(arg, "Invalid value passed to set_gpu_fan", _set_gpu_fan);
 }
 }
+static
+const char *opencl_set_gpu_fan(struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const out_success)
+{
+	if (set_fanspeed(proc->device_id, atoi(newvalue)))
+		return "Failed to set gpu_fan";
+	return NULL;
+}
 
 
 _SET_INT_LIST(gpu_memclock , (v >=     1 && v <  9999), gpu_memclock )
 _SET_INT_LIST(gpu_memclock , (v >=     1 && v <  9999), gpu_memclock )
+static
+const char *opencl_set_gpu_memclock(struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const out_success)
+{
+	if (set_memoryclock(proc->device_id, atoi(newvalue)))
+		return "Failed to set gpu_memclock";
+	return NULL;
+}
+
 _SET_INT_LIST(gpu_memdiff  , (v >= -9999 && v <= 9999), gpu_memdiff  )
 _SET_INT_LIST(gpu_memdiff  , (v >= -9999 && v <= 9999), gpu_memdiff  )
+static
+const char *opencl_set_gpu_memdiff(struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const out_success)
+{
+	struct opencl_device_data * const data = proc->device_data;
+	
+	if (!_set_gpu_memdiff(proc, newvalue))
+		return "Invalid value for gpu_memdiff";
+	
+	set_engineclock(proc->device_id, data->gpu_engine);
+	
+	return NULL;
+}
+
 _SET_INT_LIST(gpu_powertune, (v >=   -99 && v <=   99), gpu_powertune)
 _SET_INT_LIST(gpu_powertune, (v >=   -99 && v <=   99), gpu_powertune)
 _SET_INT_LIST(gpu_vddc     , (v >=     0 && v <  9999), gpu_vddc     )
 _SET_INT_LIST(gpu_vddc     , (v >=     0 && v <  9999), gpu_vddc     )
+static
+const char *opencl_set_gpu_vddc(struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const out_success)
+{
+	if (set_vddc(proc->device_id, atof(newvalue)))
+		return "Failed to set gpu_vddc";
+	return NULL;
+}
+
 _SET_INT_LIST(temp_overheat, (v >=     0 && v <   200), adl.overtemp )
 _SET_INT_LIST(temp_overheat, (v >=     0 && v <   200), adl.overtemp )
 #endif
 #endif
 
 
 #ifdef HAVE_OPENCL
 #ifdef HAVE_OPENCL
+// SHA256d "intensity" has an artificial offset of -15
+double oclthreads_to_intensity(const unsigned long oclthreads, const bool is_sha256d)
+{
+	double intensity = log2(oclthreads);
+	if (is_sha256d)
+		intensity -= 15.;
+	return intensity;
+}
+
+unsigned long intensity_to_oclthreads(double intensity, const bool is_sha256d)
+{
+	if (is_sha256d)
+		intensity += 15;
+	return pow(2, intensity);
+}
+
+double oclthreads_to_xintensity(const unsigned long oclthreads, const cl_uint max_compute_units)
+{
+	return (double)oclthreads / (double)max_compute_units / 64.;
+}
+
+unsigned long xintensity_to_oclthreads(const double xintensity, const cl_uint max_compute_units)
+{
+	return xintensity * max_compute_units * 0x40;
+}
+
 static
 static
-bool _set_intensity(struct cgpu_info * const cgpu, const char * const _val)
+bool _set_intensity(struct cgpu_info * const cgpu, const char *_val)
 {
 {
 	struct opencl_device_data * const data = cgpu->device_data;
 	struct opencl_device_data * const data = cgpu->device_data;
+	
+	data->dynamic = false;
+	data->_init_xintensity = 0;
+	
 	if (!strncasecmp(_val, "d", 1))
 	if (!strncasecmp(_val, "d", 1))
+	{
 		data->dynamic = true;
 		data->dynamic = true;
+		++_val;
+	}
+	
+	if (!strncasecmp(_val, "x", 1))
+	{
+		const double v = atof(&_val[1]);
+		if (v < 1 || v > 9999)
+			return false;
+		
+		if (cgpu->thr)
+		{
+			struct thr_info * const thr = cgpu->thr[0];
+			const int thr_id = thr->id;
+			_clState * const clState = clStates[thr_id];
+			
+			data->oclthreads = xintensity_to_oclthreads(v, clState->max_compute_units);
+		}
+		data->_init_xintensity = v;
+	}
 	else
 	else
+	if (isdigit(_val[0]))
 	{
 	{
-		const int v = atoi(_val);
+		const double v = atof(_val);
 		if (v < MIN_INTENSITY || v > MAX_GPU_INTENSITY)
 		if (v < MIN_INTENSITY || v > MAX_GPU_INTENSITY)
 			return false;
 			return false;
-		data->dynamic = false;
-		data->intensity = v;
+		data->oclthreads = intensity_to_oclthreads(v, !opt_scrypt);
 	}
 	}
+	pause_dynamic_threads(cgpu->device_id);
 	return true;
 	return true;
 }
 }
+_SET_INTERFACE(intensity)
 const char *set_intensity(char *arg)
 const char *set_intensity(char *arg)
 {
 {
 	return _set_list(arg, "Invalid value passed to intensity", _set_intensity);
 	return _set_list(arg, "Invalid value passed to intensity", _set_intensity);
@@ -493,145 +614,6 @@ _SET_INT_LIST2(gpu_threads, (v >= 1 && v <= 10), cgpu->threads)
 
 
 void write_config_opencl(FILE * const fcfg)
 void write_config_opencl(FILE * const fcfg)
 {
 {
-	int i;
-#ifdef HAVE_OPENCL
-	if (nDevs) {
-		/* Write GPU device values */
-		fputs(",\n\"intensity\" : \"", fcfg);
-		for(i = 0; i < nDevs; i++)
-		{
-			struct cgpu_info * const cgpu = &gpus[i];
-			struct opencl_device_data * const data = cgpu->device_data;
-			if (i > 0)
-				fputc(',', fcfg);
-			if (data->dynamic)
-				fputc('d', fcfg);
-			else
-				fprintf(fcfg, "%d", data->intensity);
-		}
-		fputs("\",\n\"vectors\" : \"", fcfg);
-		for(i = 0; i < nDevs; i++)
-		{
-			struct cgpu_info * const cgpu = &gpus[i];
-			struct opencl_device_data * const data = cgpu->device_data;
-			fprintf(fcfg, "%s%d", i > 0 ? "," : "",
-			        data->vwidth);
-		}
-		fputs("\",\n\"worksize\" : \"", fcfg);
-		for(i = 0; i < nDevs; i++)
-		{
-			struct cgpu_info * const cgpu = &gpus[i];
-			struct opencl_device_data * const data = cgpu->device_data;
-			fprintf(fcfg, "%s%d", i > 0 ? "," : "",
-			        (int)data->work_size);
-		}
-		fputs("\",\n\"kernel\" : \"", fcfg);
-		for(i = 0; i < nDevs; i++) {
-			struct cgpu_info * const cgpu = &gpus[i];
-			struct opencl_device_data * const data = cgpu->device_data;
-			fprintf(fcfg, "%s", i > 0 ? "," : "");
-			switch (data->kernel) {
-				case KL_NONE: // Shouldn't happen
-					break;
-				case KL_POCLBM:
-					fprintf(fcfg, "poclbm");
-					break;
-				case KL_PHATK:
-					fprintf(fcfg, "phatk");
-					break;
-				case KL_DIAKGCN:
-					fprintf(fcfg, "diakgcn");
-					break;
-				case KL_DIABLO:
-					fprintf(fcfg, "diablo");
-					break;
-				case KL_SCRYPT:
-					fprintf(fcfg, "scrypt");
-					break;
-			}
-		}
-#ifdef USE_SCRYPT
-		fputs("\",\n\"lookup-gap\" : \"", fcfg);
-		for(i = 0; i < nDevs; i++)
-		{
-			struct cgpu_info * const cgpu = &gpus[i];
-			struct opencl_device_data * const data = cgpu->device_data;
-			fprintf(fcfg, "%s%d", i > 0 ? "," : "",
-			        (int)data->opt_lg);
-		}
-		fputs("\",\n\"thread-concurrency\" : \"", fcfg);
-		for(i = 0; i < nDevs; i++)
-		{
-			struct cgpu_info * const cgpu = &gpus[i];
-			struct opencl_device_data * const data = cgpu->device_data;
-			fprintf(fcfg, "%s%d", i > 0 ? "," : "",
-			        (int)data->opt_tc);
-		}
-		fputs("\",\n\"shaders\" : \"", fcfg);
-		for(i = 0; i < nDevs; i++)
-		{
-			struct cgpu_info * const cgpu = &gpus[i];
-			struct opencl_device_data * const data = cgpu->device_data;
-			fprintf(fcfg, "%s%d", i > 0 ? "," : "",
-			        (int)data->shaders);
-		}
-#endif
-#ifdef HAVE_ADL
-		fputs("\",\n\"gpu-engine\" : \"", fcfg);
-		for(i = 0; i < nDevs; i++)
-		{
-			struct cgpu_info * const cgpu = &gpus[i];
-			struct opencl_device_data * const data = cgpu->device_data;
-			fprintf(fcfg, "%s%d-%d", i > 0 ? "," : "",
-			        data->min_engine, data->gpu_engine);
-		}
-		fputs("\",\n\"gpu-fan\" : \"", fcfg);
-		for(i = 0; i < nDevs; i++)
-		{
-			struct cgpu_info * const cgpu = &gpus[i];
-			struct opencl_device_data * const data = cgpu->device_data;
-			fprintf(fcfg, "%s%d-%d", i > 0 ? "," : "",
-			        data->min_fan, data->gpu_fan);
-		}
-		fputs("\",\n\"gpu-memclock\" : \"", fcfg);
-		for(i = 0; i < nDevs; i++)
-		{
-			struct cgpu_info * const cgpu = &gpus[i];
-			struct opencl_device_data * const data = cgpu->device_data;
-			fprintf(fcfg, "%s%d", i > 0 ? "," : "", data->gpu_memclock);
-		}
-		fputs("\",\n\"gpu-memdiff\" : \"", fcfg);
-		for(i = 0; i < nDevs; i++)
-		{
-			struct cgpu_info * const cgpu = &gpus[i];
-			struct opencl_device_data * const data = cgpu->device_data;
-			fprintf(fcfg, "%s%d", i > 0 ? "," : "", data->gpu_memdiff);
-		}
-		fputs("\",\n\"gpu-powertune\" : \"", fcfg);
-		for(i = 0; i < nDevs; i++)
-		{
-			struct cgpu_info * const cgpu = &gpus[i];
-			struct opencl_device_data * const data = cgpu->device_data;
-			fprintf(fcfg, "%s%d", i > 0 ? "," : "", data->gpu_powertune);
-		}
-		fputs("\",\n\"gpu-vddc\" : \"", fcfg);
-		for(i = 0; i < nDevs; i++)
-		{
-			struct cgpu_info * const cgpu = &gpus[i];
-			struct opencl_device_data * const data = cgpu->device_data;
-			fprintf(fcfg, "%s%1.3f", i > 0 ? "," : "", data->gpu_vddc);
-		}
-		fputs("\",\n\"temp-overheat\" : \"", fcfg);
-		for(i = 0; i < nDevs; i++)
-		{
-			struct cgpu_info * const cgpu = &gpus[i];
-			struct opencl_device_data * const data = cgpu->device_data;
-			fprintf(fcfg, "%s%d", i > 0 ? "," : "", data->adl.overtemp);
-		}
-#endif
-		fputs("\"", fcfg);
-	}
-#endif
 #ifdef HAVE_ADL
 #ifdef HAVE_ADL
 	if (opt_reorder)
 	if (opt_reorder)
 		fprintf(fcfg, ",\n\"gpu-reorder\" : true");
 		fprintf(fcfg, ",\n\"gpu-reorder\" : true");
@@ -641,6 +623,8 @@ void write_config_opencl(FILE * const fcfg)
 
 
 #ifdef HAVE_OPENCL
 #ifdef HAVE_OPENCL
 BFG_REGISTER_DRIVER(opencl_api)
 BFG_REGISTER_DRIVER(opencl_api)
+static const struct bfg_set_device_definition opencl_set_device_funcs_probe[];
+static const struct bfg_set_device_definition opencl_set_device_funcs[];
 
 
 char *print_ndevs_and_exit(int *ndevs)
 char *print_ndevs_and_exit(int *ndevs)
 {
 {
@@ -694,7 +678,9 @@ static
 void opencl_wlogprint_status(struct cgpu_info *cgpu)
 void opencl_wlogprint_status(struct cgpu_info *cgpu)
 {
 {
 	struct opencl_device_data * const data = cgpu->device_data;
 	struct opencl_device_data * const data = cgpu->device_data;
-	struct thr_info *thr;
+	struct thr_info *thr = cgpu->thr[0];
+	const int thr_id = thr->id;
+	_clState * const clState = clStates[thr_id];
 	int i;
 	int i;
 	char checkin[40];
 	char checkin[40];
 	double displayed_rolling;
 	double displayed_rolling;
@@ -702,7 +688,20 @@ void opencl_wlogprint_status(struct cgpu_info *cgpu)
 	char logline[255];
 	char logline[255];
 	strcpy(logline, ""); // In case it has no data
 	strcpy(logline, ""); // In case it has no data
 	
 	
-	tailsprintf(logline, sizeof(logline), "I:%s%d  ", (data->dynamic ? "d" : ""), data->intensity);
+	{
+		double intensity = oclthreads_to_intensity(data->oclthreads, !opt_scrypt);
+		double xintensity = oclthreads_to_xintensity(data->oclthreads, clState->max_compute_units);
+		const char *iunit = "";
+		if (xintensity - (int)xintensity < intensity - (int)intensity)
+		{
+			intensity = xintensity;
+			iunit = "x";
+		}
+		tailsprintf(logline, sizeof(logline), "I:%s%s%g ",
+		            (data->dynamic ? "d" : ""),
+		            iunit,
+		            intensity);
+	}
 #ifdef HAVE_ADL
 #ifdef HAVE_ADL
 	if (data->has_adl) {
 	if (data->has_adl) {
 		int engineclock = 0, memclock = 0, activity = 0, fanspeed = 0, fanpercent = 0, powertune = 0;
 		int engineclock = 0, memclock = 0, activity = 0, fanspeed = 0, fanpercent = 0, powertune = 0;
@@ -710,29 +709,29 @@ void opencl_wlogprint_status(struct cgpu_info *cgpu)
 
 
 		if (gpu_stats(cgpu->device_id, &temp, &engineclock, &memclock, &vddc, &activity, &fanspeed, &fanpercent, &powertune)) {
 		if (gpu_stats(cgpu->device_id, &temp, &engineclock, &memclock, &vddc, &activity, &fanspeed, &fanpercent, &powertune)) {
 			if (fanspeed != -1 || fanpercent != -1) {
 			if (fanspeed != -1 || fanpercent != -1) {
-				tailsprintf(logline, sizeof(logline), "F: ");
+				tailsprintf(logline, sizeof(logline), "F:");
 				if (fanspeed > 9999)
 				if (fanspeed > 9999)
 					fanspeed = 9999;
 					fanspeed = 9999;
 				if (fanpercent != -1)
 				if (fanpercent != -1)
 				{
 				{
-					tailsprintf(logline, sizeof(logline), "%d%% ", fanpercent);
+					tailsprintf(logline, sizeof(logline), "%d%%", fanpercent);
 					if (fanspeed != -1)
 					if (fanspeed != -1)
-						tailsprintf(logline, sizeof(logline), "(%d RPM) ", fanspeed);
+						tailsprintf(logline, sizeof(logline), "(%dRPM)", fanspeed);
 				}
 				}
 				else
 				else
-					tailsprintf(logline, sizeof(logline), "%d RPM ", fanspeed);
+					tailsprintf(logline, sizeof(logline), "%dRPM", fanspeed);
 				tailsprintf(logline, sizeof(logline), " ");
 				tailsprintf(logline, sizeof(logline), " ");
 			}
 			}
 			if (engineclock != -1)
 			if (engineclock != -1)
-				tailsprintf(logline, sizeof(logline), "E: %d MHz  ", engineclock);
+				tailsprintf(logline, sizeof(logline), "E:%dMHz ", engineclock);
 			if (memclock != -1)
 			if (memclock != -1)
-				tailsprintf(logline, sizeof(logline), "M: %d MHz  ", memclock);
+				tailsprintf(logline, sizeof(logline), "M:%dMHz ", memclock);
 			if (vddc != -1)
 			if (vddc != -1)
-				tailsprintf(logline, sizeof(logline), "V: %.3fV  ", vddc);
+				tailsprintf(logline, sizeof(logline), "V:%.3fV ", vddc);
 			if (activity != -1)
 			if (activity != -1)
-				tailsprintf(logline, sizeof(logline), "A: %d%%  ", activity);
+				tailsprintf(logline, sizeof(logline), "A:%d%% ", activity);
 			if (powertune != -1)
 			if (powertune != -1)
-				tailsprintf(logline, sizeof(logline), "P: %d%%", powertune);
+				tailsprintf(logline, sizeof(logline), "P:%d%%", powertune);
 		}
 		}
 	}
 	}
 #endif
 #endif
@@ -793,7 +792,6 @@ const char *opencl_tui_handle_choice(struct cgpu_info *cgpu, int input)
 	{
 	{
 		case 'i': case 'I':
 		case 'i': case 'I':
 		{
 		{
-			int intensity;
 			char *intvar;
 			char *intvar;
 
 
 			if (opt_scrypt) {
 			if (opt_scrypt) {
@@ -813,13 +811,9 @@ const char *opencl_tui_handle_choice(struct cgpu_info *cgpu, int input)
 				free(intvar);
 				free(intvar);
 				return "Dynamic mode enabled\n";
 				return "Dynamic mode enabled\n";
 			}
 			}
-			intensity = atoi(intvar);
-			free(intvar);
-			if (intensity < MIN_INTENSITY || intensity > MAX_INTENSITY)
+			if (!_set_intensity(cgpu, intvar))
 				return "Invalid intensity (out of range)\n";
 				return "Invalid intensity (out of range)\n";
-			data->dynamic = false;
-			data->intensity = intensity;
-			pause_dynamic_threads(cgpu->device_id);
+			free(intvar);
 			return "Intensity changed\n";
 			return "Intensity changed\n";
 		}
 		}
 		case 'r': case 'R':
 		case 'r': case 'R':
@@ -847,7 +841,6 @@ const char *opencl_tui_handle_choice(struct cgpu_info *cgpu, int input)
 
 
 
 
 #ifdef HAVE_OPENCL
 #ifdef HAVE_OPENCL
-static _clState *clStates[MAX_GPUDEVICES];
 
 
 #define CL_SET_BLKARG(blkvar) status |= clSetKernelArg(*kernel, num++, sizeof(uint), (void *)&blk->blkvar)
 #define CL_SET_BLKARG(blkvar) status |= clSetKernelArg(*kernel, num++, sizeof(uint), (void *)&blk->blkvar)
 #define CL_SET_ARG(var) status |= clSetKernelArg(*kernel, num++, sizeof(var), (void *)&var)
 #define CL_SET_ARG(var) status |= clSetKernelArg(*kernel, num++, sizeof(var), (void *)&var)
@@ -1123,25 +1116,6 @@ cl_int queue_scrypt_kernel(_clState * const clState, struct work * const work, _
 	return status;
 	return status;
 }
 }
 #endif
 #endif
-
-static void set_threads_hashes(unsigned int vectors,int64_t *hashes, size_t *globalThreads,
-			       unsigned int minthreads, __maybe_unused int *intensity)
-{
-	unsigned int threads = 0;
-
-	while (threads < minthreads) {
-		threads = 1 << ((opt_scrypt ? 0 : 15) + *intensity);
-		if (threads < minthreads) {
-			if (likely(*intensity < MAX_INTENSITY))
-				(*intensity)++;
-			else
-				threads = minthreads;
-		}
-	}
-
-	*globalThreads = threads;
-	*hashes = threads * vectors;
-}
 #endif /* HAVE_OPENCL */
 #endif /* HAVE_OPENCL */
 
 
 
 
@@ -1308,6 +1282,10 @@ static int opencl_autodetect()
 		data->sensor = cn;
 		data->sensor = cn;
 #endif
 #endif
 		
 		
+		cgpu->set_device_funcs = opencl_set_device_funcs_probe;
+		cgpu_set_defaults(cgpu);
+		cgpu->set_device_funcs = opencl_set_device_funcs;
+		
 		add_cgpu(cgpu);
 		add_cgpu(cgpu);
 	}
 	}
 
 
@@ -1401,6 +1379,9 @@ static struct api_data*
 get_opencl_api_extra_device_status(struct cgpu_info *gpu)
 get_opencl_api_extra_device_status(struct cgpu_info *gpu)
 {
 {
 	struct opencl_device_data * const data = gpu->device_data;
 	struct opencl_device_data * const data = gpu->device_data;
+	struct thr_info * const thr = gpu->thr[0];
+	const int thr_id = thr->id;
+	_clState * const clState = clStates[thr_id];
 	struct api_data*root = NULL;
 	struct api_data*root = NULL;
 
 
 	float gt, gv;
 	float gt, gv;
@@ -1418,11 +1399,17 @@ get_opencl_api_extra_device_status(struct cgpu_info *gpu)
 	root = api_add_int(root, "Powertune", &pt, true);
 	root = api_add_int(root, "Powertune", &pt, true);
 
 
 	char intensity[20];
 	char intensity[20];
+	uint32_t oclthreads = data->oclthreads;
+	double intensityf = oclthreads_to_intensity(oclthreads, !opt_scrypt);
+	double xintensity = oclthreads_to_xintensity(oclthreads, clState->max_compute_units);
 	if (data->dynamic)
 	if (data->dynamic)
 		strcpy(intensity, "D");
 		strcpy(intensity, "D");
 	else
 	else
-		sprintf(intensity, "%d", data->intensity);
+		sprintf(intensity, "%g", intensityf);
 	root = api_add_string(root, "Intensity", intensity, true);
 	root = api_add_string(root, "Intensity", intensity, true);
+	root = api_add_uint32(root, "OCLThreads", &oclthreads, true);
+	root = api_add_double(root, "CIntensity", &intensityf, true);
+	root = api_add_double(root, "XIntensity", &xintensity, true);
 
 
 	return root;
 	return root;
 }
 }
@@ -1616,17 +1603,26 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work,
 		cgtime(&tv_gpuend);
 		cgtime(&tv_gpuend);
 		gpu_us = us_tdiff(&tv_gpuend, &data->tv_gpustart) / data->intervals;
 		gpu_us = us_tdiff(&tv_gpuend, &data->tv_gpustart) / data->intervals;
 		if (gpu_us > dynamic_us) {
 		if (gpu_us > dynamic_us) {
-			if (data->intensity > MIN_INTENSITY)
-				--data->intensity;
+			const unsigned long min_oclthreads = intensity_to_oclthreads(MIN_INTENSITY, !opt_scrypt);
+			data->oclthreads /= 2;
+			if (data->oclthreads < min_oclthreads)
+				data->oclthreads = min_oclthreads;
 		} else if (gpu_us < dynamic_us / 2) {
 		} else if (gpu_us < dynamic_us / 2) {
-			if (data->intensity < MAX_INTENSITY)
-				++data->intensity;
+			const unsigned long max_oclthreads = intensity_to_oclthreads(MAX_INTENSITY, !opt_scrypt);
+			data->oclthreads *= 2;
+			if (data->oclthreads > max_oclthreads)
+				data->oclthreads = max_oclthreads;
 		}
 		}
 		memcpy(&(data->tv_gpustart), &tv_gpuend, sizeof(struct timeval));
 		memcpy(&(data->tv_gpustart), &tv_gpuend, sizeof(struct timeval));
 		data->intervals = 0;
 		data->intervals = 0;
 	}
 	}
 
 
-	set_threads_hashes(clState->vwidth, &hashes, globalThreads, localThreads[0], &data->intensity);
+	if (data->oclthreads < localThreads[0])
+		data->oclthreads = localThreads[0];
+	globalThreads[0] = data->oclthreads;
+	hashes = globalThreads[0];
+	hashes *= clState->vwidth;
+	
 	if (hashes > gpu->max_hashes)
 	if (hashes > gpu->max_hashes)
 		gpu->max_hashes = hashes;
 		gpu->max_hashes = hashes;
 
 
@@ -1695,6 +1691,60 @@ static void opencl_thread_shutdown(struct thr_info *thr)
 	clReleaseContext(clState->context);
 	clReleaseContext(clState->context);
 }
 }
 
 
+static
+const char *opencl_cannot_set(struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const out_success)
+{
+	return "Cannot set at runtime (use --set-device on commandline)";
+}
+
+static const struct bfg_set_device_definition opencl_set_device_funcs_probe[] = {
+	{"intensity", opencl_init_intensity},
+	{"kernel", opencl_init_kernel},
+	{"threads", opencl_init_gpu_threads},
+	{"vector", opencl_init_vector},
+	{"work_size", opencl_init_worksize},
+#ifdef HAVE_ADL
+	{"adl_mapping", opencl_init_gpu_map},
+	{"clock", opencl_init_gpu_engine},
+	{"fan", opencl_init_gpu_fan},
+	{"memclock", opencl_init_gpu_memclock},
+	{"memdiff", opencl_init_gpu_memdiff},
+	{"powertune", opencl_init_gpu_powertune},
+	{"temp_overheat", opencl_init_temp_overheat},
+	{"voltage", opencl_init_gpu_vddc},
+#endif
+#ifdef USE_SCRYPT
+	{"shaders", opencl_init_shaders},
+	{"lookup_gap", opencl_init_lookup_gap},
+	{"thread_concurrency", opencl_init_thread_concurrency},
+#endif
+	{NULL}
+};
+
+static const struct bfg_set_device_definition opencl_set_device_funcs[] = {
+	{"intensity", opencl_init_intensity, "Intensity of GPU scanning (d, -10 -> 31, or x1 to x9999)"},
+	{"kernel", opencl_cannot_set, "Mining kernel code to use"},
+	{"threads", opencl_cannot_set, "Number of threads"},
+	{"vector", opencl_cannot_set, ""},
+	{"work_size", opencl_cannot_set, ""},
+#ifdef HAVE_ADL
+	{"adl_mapping", opencl_cannot_set, "Map to ADL device"},
+	{"clock", opencl_set_gpu_engine, "GPU engine clock"},
+	{"fan", opencl_set_gpu_fan, "GPU fan percentage range"},
+	{"memclock", opencl_set_gpu_memclock, "GPU memory clock"},
+	{"memdiff", opencl_set_gpu_memdiff, "Clock speed difference between GPU and memory (auto-gpu mode only)"},
+	{"powertune", opencl_cannot_set, "GPU powertune percentage"},
+	{"temp_overheat", opencl_init_temp_overheat, "Overheat temperature when automatically managing fan and GPU speeds"},
+	{"voltage", opencl_set_gpu_vddc, "GPU voltage"},
+#endif
+#ifdef USE_SCRYPT
+	{"shaders", opencl_cannot_set, "GPU shaders per card (scrypt only)"},
+	{"lookup_gap", opencl_cannot_set, "GPU lookup gap (scrypt only)"},
+	{"thread_concurrency", opencl_cannot_set, "GPU thread concurrency (scrypt only)"},
+#endif
+	{NULL}
+};
+
 struct device_drv opencl_api = {
 struct device_drv opencl_api = {
 	.dname = "opencl",
 	.dname = "opencl",
 	.name = "OCL",
 	.name = "OCL",

+ 6 - 1
driver-opencl.h

@@ -14,7 +14,8 @@ struct opencl_device_data {
 	bool mapped;
 	bool mapped;
 	int virtual_gpu;
 	int virtual_gpu;
 	int virtual_adl;
 	int virtual_adl;
-	int intensity;
+	unsigned long oclthreads;
+	double _init_xintensity;
 	bool dynamic;
 	bool dynamic;
 	
 	
 	cl_uint vwidth;
 	cl_uint vwidth;
@@ -49,6 +50,10 @@ struct opencl_device_data {
 #endif
 #endif
 };
 };
 
 
+extern double oclthreads_to_intensity(unsigned long oclthreads, bool is_sha256d);
+extern unsigned long intensity_to_oclthreads(double intensity, bool is_sha256d);
+extern unsigned long xintensity_to_oclthreads(double xintensity, cl_uint max_compute_units);
+
 struct opencl_work_data {
 struct opencl_work_data {
 	cl_uint ctx_a; cl_uint ctx_b; cl_uint ctx_c; cl_uint ctx_d;
 	cl_uint ctx_a; cl_uint ctx_b; cl_uint ctx_c; cl_uint ctx_d;
 	cl_uint ctx_e; cl_uint ctx_f; cl_uint ctx_g; cl_uint ctx_h;
 	cl_uint ctx_e; cl_uint ctx_f; cl_uint ctx_g; cl_uint ctx_h;

+ 15 - 38
miner.c

@@ -2052,55 +2052,41 @@ static struct opt_table opt_config_table[] = {
 	OPT_WITH_ARG("--gpu-platform",
 	OPT_WITH_ARG("--gpu-platform",
 		     set_int_0_to_9999, opt_show_intval, &opt_platform_id,
 		     set_int_0_to_9999, opt_show_intval, &opt_platform_id,
 		     "Select OpenCL platform ID to use for GPU mining"),
 		     "Select OpenCL platform ID to use for GPU mining"),
-	OPT_WITH_ARG("--gpu-threads",
-		     set_gpu_threads, opt_show_intval, &opt_g_threads,
-		     "Number of threads per GPU (1 - 10) - one value for all or separate by commas for per card"),
-	OPT_WITH_ARG("-g",
+	OPT_WITH_ARG("--gpu-threads|-g",
 	             set_gpu_threads, opt_show_intval, &opt_g_threads,
 	             set_gpu_threads, opt_show_intval, &opt_g_threads,
 	             opt_hidden),
 	             opt_hidden),
 #ifdef HAVE_ADL
 #ifdef HAVE_ADL
 	OPT_WITH_ARG("--gpu-engine",
 	OPT_WITH_ARG("--gpu-engine",
 		     set_gpu_engine, NULL, NULL,
 		     set_gpu_engine, NULL, NULL,
-		     "GPU engine (over)clock range in MHz - one value, range and/or comma separated list (e.g. 850-900,900,750-850)"),
+	             opt_hidden),
 	OPT_WITH_ARG("--gpu-fan",
 	OPT_WITH_ARG("--gpu-fan",
 		     set_gpu_fan, NULL, NULL,
 		     set_gpu_fan, NULL, NULL,
-		     "GPU fan percentage range - one value, range and/or comma separated list (e.g. 0-85,85,65)"),
+	             opt_hidden),
 	OPT_WITH_ARG("--gpu-map",
 	OPT_WITH_ARG("--gpu-map",
 		     set_gpu_map, NULL, NULL,
 		     set_gpu_map, NULL, NULL,
 		     "Map OpenCL to ADL device order manually, paired CSV (e.g. 1:0,2:1 maps OpenCL 1 to ADL 0, 2 to 1)"),
 		     "Map OpenCL to ADL device order manually, paired CSV (e.g. 1:0,2:1 maps OpenCL 1 to ADL 0, 2 to 1)"),
 	OPT_WITH_ARG("--gpu-memclock",
 	OPT_WITH_ARG("--gpu-memclock",
 		     set_gpu_memclock, NULL, NULL,
 		     set_gpu_memclock, NULL, NULL,
-		     "Set the GPU memory (over)clock in MHz - one value for all or separate by commas for per card"),
+	             opt_hidden),
 	OPT_WITH_ARG("--gpu-memdiff",
 	OPT_WITH_ARG("--gpu-memdiff",
 		     set_gpu_memdiff, NULL, NULL,
 		     set_gpu_memdiff, NULL, NULL,
-		     "Set a fixed difference in clock speed between the GPU and memory in auto-gpu mode"),
+	             opt_hidden),
 	OPT_WITH_ARG("--gpu-powertune",
 	OPT_WITH_ARG("--gpu-powertune",
 		     set_gpu_powertune, NULL, NULL,
 		     set_gpu_powertune, NULL, NULL,
-		     "Set the GPU powertune percentage - one value for all or separate by commas for per card"),
+	             opt_hidden),
 	OPT_WITHOUT_ARG("--gpu-reorder",
 	OPT_WITHOUT_ARG("--gpu-reorder",
 			opt_set_bool, &opt_reorder,
 			opt_set_bool, &opt_reorder,
 			"Attempt to reorder GPU devices according to PCI Bus ID"),
 			"Attempt to reorder GPU devices according to PCI Bus ID"),
 	OPT_WITH_ARG("--gpu-vddc",
 	OPT_WITH_ARG("--gpu-vddc",
 		     set_gpu_vddc, NULL, NULL,
 		     set_gpu_vddc, NULL, NULL,
-		     "Set the GPU voltage in Volts - one value for all or separate by commas for per card"),
+	             opt_hidden),
 #endif
 #endif
 #ifdef USE_SCRYPT
 #ifdef USE_SCRYPT
 	OPT_WITH_ARG("--lookup-gap",
 	OPT_WITH_ARG("--lookup-gap",
 		     set_lookup_gap, NULL, NULL,
 		     set_lookup_gap, NULL, NULL,
-		     "Set GPU lookup gap for scrypt mining, comma separated"),
-	OPT_WITH_ARG("--intensity",
-		     set_intensity, NULL, NULL,
-		     "Intensity of GPU scanning (d or " MIN_SHA_INTENSITY_STR
-		     " -> " MAX_SCRYPT_INTENSITY_STR
-		     ",default: d to maintain desktop interactivity)"),
-#else
-	OPT_WITH_ARG("--intensity",
-		     set_intensity, NULL, NULL,
-		     "Intensity of GPU scanning (d or " MIN_SHA_INTENSITY_STR
-		     " -> " MAX_SHA_INTENSITY_STR
-		     ",default: d to maintain desktop interactivity)"),
+	             opt_hidden),
 #endif
 #endif
-	OPT_WITH_ARG("-I",
+	OPT_WITH_ARG("--intensity|-I",
 	             set_intensity, NULL, NULL,
 	             set_intensity, NULL, NULL,
 	             opt_hidden),
 	             opt_hidden),
 #endif
 #endif
@@ -2113,10 +2099,7 @@ static struct opt_table opt_config_table[] = {
 	             opt_hidden),
 	             opt_hidden),
 #endif
 #endif
 #ifdef HAVE_OPENCL
 #ifdef HAVE_OPENCL
-	OPT_WITH_ARG("--kernel",
-		     set_kernel, NULL, NULL,
-		     "Override sha256 kernel to use (diablo, poclbm, phatk or diakgcn) - one value or comma separated"),
-	OPT_WITH_ARG("-k",
+	OPT_WITH_ARG("--kernel|-k",
 	             set_kernel, NULL, NULL,
 	             set_kernel, NULL, NULL,
 	             opt_hidden),
 	             opt_hidden),
 #endif
 #endif
@@ -2309,7 +2292,7 @@ static struct opt_table opt_config_table[] = {
 #if defined(USE_SCRYPT) && defined(HAVE_OPENCL)
 #if defined(USE_SCRYPT) && defined(HAVE_OPENCL)
 	OPT_WITH_ARG("--shaders",
 	OPT_WITH_ARG("--shaders",
 		     set_shaders, NULL, NULL,
 		     set_shaders, NULL, NULL,
-		     "GPU shaders per card for tuning scrypt, comma separated"),
+	             opt_hidden),
 #endif
 #endif
 #ifdef HAVE_PWD_H
 #ifdef HAVE_PWD_H
         OPT_WITH_ARG("--setuid",
         OPT_WITH_ARG("--setuid",
@@ -2359,7 +2342,7 @@ static struct opt_table opt_config_table[] = {
 #ifdef HAVE_ADL
 #ifdef HAVE_ADL
 	OPT_WITH_ARG("--temp-overheat",
 	OPT_WITH_ARG("--temp-overheat",
 		     set_temp_overheat, opt_show_intval, &opt_overheattemp,
 		     set_temp_overheat, opt_show_intval, &opt_overheattemp,
-		     "Overheat temperature when automatically managing fan and GPU speeds, one value or comma separated list"),
+	             opt_hidden),
 #endif
 #endif
 	OPT_WITH_ARG("--temp-target",
 	OPT_WITH_ARG("--temp-target",
 		     set_temp_target, NULL, NULL,
 		     set_temp_target, NULL, NULL,
@@ -2375,7 +2358,7 @@ static struct opt_table opt_config_table[] = {
 #if defined(USE_SCRYPT) && defined(HAVE_OPENCL)
 #if defined(USE_SCRYPT) && defined(HAVE_OPENCL)
 	OPT_WITH_ARG("--thread-concurrency",
 	OPT_WITH_ARG("--thread-concurrency",
 		     set_thread_concurrency, NULL, NULL,
 		     set_thread_concurrency, NULL, NULL,
-		     "Set GPU thread concurrency for scrypt mining, comma separated"),
+	             opt_hidden),
 #endif
 #endif
 #ifdef USE_UNICODE
 #ifdef USE_UNICODE
 	OPT_WITHOUT_ARG("--unicode",
 	OPT_WITHOUT_ARG("--unicode",
@@ -2389,10 +2372,7 @@ static struct opt_table opt_config_table[] = {
 		     set_user, NULL, NULL,
 		     set_user, NULL, NULL,
 		     "Username for bitcoin JSON-RPC server"),
 		     "Username for bitcoin JSON-RPC server"),
 #ifdef HAVE_OPENCL
 #ifdef HAVE_OPENCL
-	OPT_WITH_ARG("--vectors",
-		     set_vector, NULL, NULL,
-		     "Override detected optimal vector (1, 2 or 4) - one value or comma separated list"),
-	OPT_WITH_ARG("-v",
+	OPT_WITH_ARG("--vectors|-v",
 	             set_vector, NULL, NULL,
 	             set_vector, NULL, NULL,
 	             opt_hidden),
 	             opt_hidden),
 #endif
 #endif
@@ -2403,10 +2383,7 @@ static struct opt_table opt_config_table[] = {
 	                opt_set_bool, &opt_weighed_stats,
 	                opt_set_bool, &opt_weighed_stats,
 	                "Display statistics weighed to difficulty 1"),
 	                "Display statistics weighed to difficulty 1"),
 #ifdef HAVE_OPENCL
 #ifdef HAVE_OPENCL
-	OPT_WITH_ARG("--worksize",
-		     set_worksize, NULL, NULL,
-		     "Override detected optimal worksize - one value or comma separated list"),
-	OPT_WITH_ARG("-w",
+	OPT_WITH_ARG("--worksize|-w",
 	             set_worksize, NULL, NULL,
 	             set_worksize, NULL, NULL,
 	             opt_hidden),
 	             opt_hidden),
 #endif
 #endif

+ 9 - 0
ocl.c

@@ -552,6 +552,15 @@ _clState *initCl(unsigned int gpu, char *name, size_t nameSize)
 	}
 	}
 	applog(LOG_DEBUG, "Max work group size reported %"PRId64, (int64_t)clState->max_work_size);
 	applog(LOG_DEBUG, "Max work group size reported %"PRId64, (int64_t)clState->max_work_size);
 
 
+	status = clGetDeviceInfo(devices[gpu], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(clState->max_compute_units), (void *)&clState->max_compute_units, NULL);
+	if (status != CL_SUCCESS) {
+		applog(LOG_ERR, "Error %d: Failed to clGetDeviceInfo when trying to get CL_DEVICE_MAX_COMPUTE_UNITS", status);
+		return NULL;
+	}
+	if (data->_init_xintensity)
+		data->oclthreads = xintensity_to_oclthreads(data->_init_xintensity, clState->max_compute_units);
+	applog(LOG_DEBUG, "Max compute units reported %u", (unsigned)clState->max_compute_units);
+	
 	status = clGetDeviceInfo(devices[gpu], CL_DEVICE_MAX_MEM_ALLOC_SIZE , sizeof(cl_ulong), (void *)&data->max_alloc, NULL);
 	status = clGetDeviceInfo(devices[gpu], CL_DEVICE_MAX_MEM_ALLOC_SIZE , sizeof(cl_ulong), (void *)&data->max_alloc, NULL);
 	if (status != CL_SUCCESS) {
 	if (status != CL_SUCCESS) {
 		applog(LOG_ERR, "Error %d: Failed to clGetDeviceInfo when trying to get CL_DEVICE_MAX_MEM_ALLOC_SIZE", status);
 		applog(LOG_ERR, "Error %d: Failed to clGetDeviceInfo when trying to get CL_DEVICE_MAX_MEM_ALLOC_SIZE", status);

+ 1 - 0
ocl.h

@@ -27,6 +27,7 @@ typedef struct {
 	cl_uint vwidth;
 	cl_uint vwidth;
 	size_t max_work_size;
 	size_t max_work_size;
 	size_t wsize;
 	size_t wsize;
+	cl_uint max_compute_units;
 	enum cl_kernels chosen_kernel;
 	enum cl_kernels chosen_kernel;
 } _clState;
 } _clState;