On user level this fixes dead-lock of OpenCL render on Intel Iris GPUs.
Note that this patch does not include change in the logic which allows
or disallows OpenCL platforms to be used, that will happen after the
kernel fix is known to be fine for the currently officially supported
platforms.
The dead-lock was caused by wrong usage of memory barriers: as per the
OpenCL specification the barrier is to be executed by the entire work
group. This means, that the following code is invalid:
void foo() {
if (some_condition) {
return;
}
barrier(CLK_LOCAL_MEM_FENCE);
}
void bar() {
foo();
}
The Cycles code was mentioning this as an invalid code on CPU, while in
fact this is invalid as per specification. From the implementation side
this change removes the ifdefs around the CPU-only barrier logic, and
is implementing similar logic in the shader setup kernel.
Tested on NUC8i7HVK NUC.
The root cause of the dead-lock was identified by Max Dmitrichenko.
There is no measurable difference in performance of currently supported
OpenCL platforms.
Differential Revision: https://developer.blender.org/D9039
74 lines
2.8 KiB
C++
74 lines
2.8 KiB
C++
/*
|
|
* Copyright 2011-2017 Blender Foundation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
/* This kernel sets up the ShaderData structure from the values computed
|
|
* by the previous kernels.
|
|
*
|
|
* It also identifies the rays of state RAY_TO_REGENERATE and enqueues them
|
|
* in QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue.
|
|
*/
|
|
ccl_device void kernel_shader_setup(KernelGlobals *kg,
|
|
ccl_local_param unsigned int *local_queue_atomics)
|
|
{
|
|
/* Enqeueue RAY_TO_REGENERATE rays into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. */
|
|
if (ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
|
|
*local_queue_atomics = 0;
|
|
}
|
|
ccl_barrier(CCL_LOCAL_MEM_FENCE);
|
|
|
|
int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
|
|
int queue_index = kernel_split_params.queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS];
|
|
if (ray_index < queue_index) {
|
|
ray_index = get_ray_index(kg,
|
|
ray_index,
|
|
QUEUE_ACTIVE_AND_REGENERATED_RAYS,
|
|
kernel_split_state.queue_data,
|
|
kernel_split_params.queue_size,
|
|
0);
|
|
} else {
|
|
ray_index = QUEUE_EMPTY_SLOT;
|
|
}
|
|
|
|
char enqueue_flag = (IS_STATE(kernel_split_state.ray_state, ray_index, RAY_TO_REGENERATE)) ? 1 :
|
|
0;
|
|
enqueue_ray_index_local(ray_index,
|
|
QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
|
|
enqueue_flag,
|
|
kernel_split_params.queue_size,
|
|
local_queue_atomics,
|
|
kernel_split_state.queue_data,
|
|
kernel_split_params.queue_index);
|
|
|
|
/* Continue on with shader evaluation. */
|
|
if (IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE)) {
|
|
Intersection isect = kernel_split_state.isect[ray_index];
|
|
Ray ray = kernel_split_state.ray[ray_index];
|
|
ShaderData *sd = kernel_split_sd(sd, ray_index);
|
|
|
|
shader_setup_from_ray(kg, sd, &isect, &ray);
|
|
|
|
#ifdef __VOLUME__
|
|
if (sd->flag & SD_HAS_ONLY_VOLUME) {
|
|
ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_HAS_ONLY_VOLUME);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
CCL_NAMESPACE_END
|