diff --git a/scripts/core/INTRO.rst b/scripts/core/INTRO.rst index 1f319d6884..d2f2888b53 100644 --- a/scripts/core/INTRO.rst +++ b/scripts/core/INTRO.rst @@ -295,6 +295,8 @@ Layers currently included with the runtime are as follows: - Description * - UR_LAYER_PARAMETER_VALIDATION - Enables non-adapter-specific parameter validation (e.g. checking for null values). + * - UR_LAYER_BOUNDS_CHECKING + - Enables non-adapter-specific bounds checking of USM allocations for enqueued commands. Automatically enables UR_LAYER_PARAMETER_VALIDATION. * - UR_LAYER_LEAK_CHECKING - Performs some leak checking for API calls involving object creation/destruction. * - UR_LAYER_LIFETIME_VALIDATION diff --git a/scripts/templates/valddi.cpp.mako b/scripts/templates/valddi.cpp.mako index 778595b052..29938b9fc0 100644 --- a/scripts/templates/valddi.cpp.mako +++ b/scripts/templates/valddi.cpp.mako @@ -57,8 +57,16 @@ namespace ur_validation_layer { %for key, values in sorted_param_checks: %for val in values: - if( ${val} ) + %if 'boundsError' in val: + if ( getContext()->enableBoundsChecking ) { + if ( ${val} ) { + return ${key}; + } + } + %else: + if ( ${val} ) return ${key}; + %endif %endfor %endfor @@ -178,9 +186,13 @@ namespace ur_validation_layer if (enabledLayerNames.count(nameFullValidation)) { enableParameterValidation = true; + enableBoundsChecking = true; enableLeakChecking = true; enableLifetimeValidation = true; } else { + if (enabledLayerNames.count(nameBoundsChecking)) { + enableBoundsChecking = true; + } if (enabledLayerNames.count(nameParameterValidation)) { enableParameterValidation = true; } diff --git a/source/loader/layers/validation/ur_valddi.cpp b/source/loader/layers/validation/ur_valddi.cpp index 2b5b99c7d8..7bca342ecf 100644 --- a/source/loader/layers/validation/ur_valddi.cpp +++ b/source/loader/layers/validation/ur_valddi.cpp @@ -4822,9 +4822,11 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueMemBufferRead( return UR_RESULT_ERROR_INVALID_EVENT_WAIT_LIST; } - if (auto boundsError = bounds(hBuffer, offset, size); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hBuffer, offset, size); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } if (phEventWaitList != NULL && numEventsInWaitList > 0) { @@ -4902,9 +4904,11 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueMemBufferWrite( return UR_RESULT_ERROR_INVALID_EVENT_WAIT_LIST; } - if (auto boundsError = bounds(hBuffer, offset, size); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hBuffer, offset, size); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } if (phEventWaitList != NULL && numEventsInWaitList > 0) { @@ -5033,9 +5037,11 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueMemBufferReadRect( return UR_RESULT_ERROR_INVALID_SIZE; } - if (auto boundsError = bounds(hBuffer, bufferOrigin, region); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hBuffer, bufferOrigin, region); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } if (phEventWaitList != NULL && numEventsInWaitList > 0) { @@ -5168,9 +5174,11 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueMemBufferWriteRect( return UR_RESULT_ERROR_INVALID_SIZE; } - if (auto boundsError = bounds(hBuffer, bufferOrigin, region); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hBuffer, bufferOrigin, region); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } if (phEventWaitList != NULL && numEventsInWaitList > 0) { @@ -5248,14 +5256,18 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueMemBufferCopy( return UR_RESULT_ERROR_INVALID_EVENT_WAIT_LIST; } - if (auto boundsError = bounds(hBufferSrc, srcOffset, size); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hBufferSrc, srcOffset, size); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } - if (auto boundsError = bounds(hBufferDst, dstOffset, size); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hBufferDst, dstOffset, size); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } if (phEventWaitList != NULL && numEventsInWaitList > 0) { @@ -5383,14 +5395,18 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueMemBufferCopyRect( return UR_RESULT_ERROR_INVALID_SIZE; } - if (auto boundsError = bounds(hBufferSrc, srcOrigin, region); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hBufferSrc, srcOrigin, region); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } - if (auto boundsError = bounds(hBufferDst, dstOrigin, region); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hBufferDst, dstOrigin, region); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } if (phEventWaitList != NULL && numEventsInWaitList > 0) { @@ -5492,9 +5508,11 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueMemBufferFill( return UR_RESULT_ERROR_INVALID_SIZE; } - if (auto boundsError = bounds(hBuffer, offset, size); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hBuffer, offset, size); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } if (phEventWaitList != NULL && numEventsInWaitList > 0) { @@ -5579,9 +5597,11 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueMemImageRead( return UR_RESULT_ERROR_INVALID_SIZE; } - if (auto boundsError = boundsImage(hImage, origin, region); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = boundsImage(hImage, origin, region); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } if (phEventWaitList != NULL && numEventsInWaitList > 0) { @@ -5667,9 +5687,11 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueMemImageWrite( return UR_RESULT_ERROR_INVALID_SIZE; } - if (auto boundsError = boundsImage(hImage, origin, region); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = boundsImage(hImage, origin, region); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } if (phEventWaitList != NULL && numEventsInWaitList > 0) { @@ -5756,14 +5778,18 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueMemImageCopy( return UR_RESULT_ERROR_INVALID_SIZE; } - if (auto boundsError = boundsImage(hImageSrc, srcOrigin, region); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = boundsImage(hImageSrc, srcOrigin, region); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } - if (auto boundsError = boundsImage(hImageDst, dstOrigin, region); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = boundsImage(hImageDst, dstOrigin, region); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } if (phEventWaitList != NULL && numEventsInWaitList > 0) { @@ -5850,9 +5876,11 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueMemBufferMap( return UR_RESULT_ERROR_INVALID_EVENT_WAIT_LIST; } - if (auto boundsError = bounds(hBuffer, offset, size); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hBuffer, offset, size); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } if (phEventWaitList != NULL && numEventsInWaitList > 0) { @@ -6012,9 +6040,11 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueUSMFill( return UR_RESULT_ERROR_INVALID_EVENT_WAIT_LIST; } - if (auto boundsError = bounds(hQueue, pMem, 0, size); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hQueue, pMem, 0, size); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } if (phEventWaitList != NULL && numEventsInWaitList > 0) { @@ -6089,14 +6119,18 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueUSMMemcpy( return UR_RESULT_ERROR_INVALID_EVENT_WAIT_LIST; } - if (auto boundsError = bounds(hQueue, pDst, 0, size); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hQueue, pDst, 0, size); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } - if (auto boundsError = bounds(hQueue, pSrc, 0, size); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hQueue, pSrc, 0, size); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } if (phEventWaitList != NULL && numEventsInWaitList > 0) { @@ -6169,9 +6203,11 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueUSMPrefetch( return UR_RESULT_ERROR_INVALID_EVENT_WAIT_LIST; } - if (auto boundsError = bounds(hQueue, pMem, 0, size); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hQueue, pMem, 0, size); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } if (phEventWaitList != NULL && numEventsInWaitList > 0) { @@ -6230,9 +6266,11 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueUSMAdvise( return UR_RESULT_ERROR_INVALID_SIZE; } - if (auto boundsError = bounds(hQueue, pMem, 0, size); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hQueue, pMem, 0, size); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } } @@ -6332,9 +6370,11 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueUSMFill2D( return UR_RESULT_ERROR_INVALID_EVENT_WAIT_LIST; } - if (auto boundsError = bounds(hQueue, pMem, 0, pitch * height); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hQueue, pMem, 0, pitch * height); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } if (phEventWaitList != NULL && numEventsInWaitList > 0) { @@ -6431,14 +6471,18 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueUSMMemcpy2D( return UR_RESULT_ERROR_INVALID_EVENT_WAIT_LIST; } - if (auto boundsError = bounds(hQueue, pDst, 0, dstPitch * height); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hQueue, pDst, 0, dstPitch * height); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } - if (auto boundsError = bounds(hQueue, pSrc, 0, srcPitch * height); - boundsError != UR_RESULT_SUCCESS) { - return boundsError; + if (getContext()->enableBoundsChecking) { + if (auto boundsError = bounds(hQueue, pSrc, 0, srcPitch * height); + boundsError != UR_RESULT_SUCCESS) { + return boundsError; + } } if (phEventWaitList != NULL && numEventsInWaitList > 0) { @@ -10997,9 +11041,13 @@ ur_result_t context_t::init(ur_dditable_t *dditable, if (enabledLayerNames.count(nameFullValidation)) { enableParameterValidation = true; + enableBoundsChecking = true; enableLeakChecking = true; enableLifetimeValidation = true; } else { + if (enabledLayerNames.count(nameBoundsChecking)) { + enableBoundsChecking = true; + } if (enabledLayerNames.count(nameParameterValidation)) { enableParameterValidation = true; } diff --git a/source/loader/layers/validation/ur_validation_layer.hpp b/source/loader/layers/validation/ur_validation_layer.hpp index aa3d4629b7..642829f7f0 100644 --- a/source/loader/layers/validation/ur_validation_layer.hpp +++ b/source/loader/layers/validation/ur_validation_layer.hpp @@ -24,6 +24,7 @@ class __urdlllocal context_t : public proxy_layer_context_t, public AtomicSingleton { public: bool enableParameterValidation = false; + bool enableBoundsChecking = false; bool enableLeakChecking = false; bool enableLifetimeValidation = false; logger::Logger logger; @@ -35,7 +36,7 @@ class __urdlllocal context_t : public proxy_layer_context_t, static std::vector getNames() { return {nameFullValidation, nameParameterValidation, nameLeakChecking, - nameLifetimeValidation}; + nameBoundsChecking, nameLifetimeValidation}; } ur_result_t init(ur_dditable_t *dditable, const std::set &enabledLayerNames, @@ -49,6 +50,8 @@ class __urdlllocal context_t : public proxy_layer_context_t, "UR_LAYER_FULL_VALIDATION"; inline static const std::string nameParameterValidation = "UR_LAYER_PARAMETER_VALIDATION"; + inline static const std::string nameBoundsChecking = + "UR_LAYER_BOUNDS_CHECKING"; inline static const std::string nameLeakChecking = "UR_LAYER_LEAK_CHECKING"; inline static const std::string nameLifetimeValidation = "UR_LAYER_LIFETIME_VALIDATION";