Initial Grease Pencil 3.0 stage #106848

Merged
Falk David merged 224 commits from filedescriptor/blender:grease-pencil-v3 into main 2023-05-30 11:14:22 +02:00
117 changed files with 756 additions and 602 deletions
Showing only changes of commit 63ee6f614a - Show all commits

View File

@ -374,7 +374,7 @@ def external_script_add_origin_if_needed(args: argparse.Namespace,
# - Rename remote "upstream" to "origin", which takes care of changing the names of # - Rename remote "upstream" to "origin", which takes care of changing the names of
# remotes the local branches are tracking. # remotes the local branches are tracking.
# #
# - Change the URL to the "origin", which so was was still pointing to upstream. # - Change the URL to the "origin", which was still pointing to upstream.
# #
# - Re-introduce the "upstream" remote, with the same URL as it had prior to rename. # - Re-introduce the "upstream" remote, with the same URL as it had prior to rename.

View File

@ -24,3 +24,4 @@ Several people provided fixes:
- Aaron Carlisle - Aaron Carlisle
- Sebastian Parborg - Sebastian Parborg
- Leon Zandman - Leon Zandman
- Richard Antalik

View File

@ -124,7 +124,7 @@ Device_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
} }
PyDoc_STRVAR(M_aud_Device_lock_doc, PyDoc_STRVAR(M_aud_Device_lock_doc,
".. classmethod:: lock()\n\n" ".. method:: lock()\n\n"
" Locks the device so that it's guaranteed, that no samples are\n" " Locks the device so that it's guaranteed, that no samples are\n"
" read from the streams until :meth:`unlock` is called.\n" " read from the streams until :meth:`unlock` is called.\n"
" This is useful if you want to do start/stop/pause/resume some\n" " This is useful if you want to do start/stop/pause/resume some\n"
@ -152,7 +152,7 @@ Device_lock(Device* self)
} }
PyDoc_STRVAR(M_aud_Device_play_doc, PyDoc_STRVAR(M_aud_Device_play_doc,
".. classmethod:: play(sound, keep=False)\n\n" ".. method:: play(sound, keep=False)\n\n"
" Plays a sound.\n\n" " Plays a sound.\n\n"
" :arg sound: The sound to play.\n" " :arg sound: The sound to play.\n"
" :type sound: :class:`Sound`\n" " :type sound: :class:`Sound`\n"
@ -212,7 +212,7 @@ Device_play(Device* self, PyObject* args, PyObject* kwds)
} }
PyDoc_STRVAR(M_aud_Device_stopAll_doc, PyDoc_STRVAR(M_aud_Device_stopAll_doc,
".. classmethod:: stopAll()\n\n" ".. method:: stopAll()\n\n"
" Stops all playing and paused sounds."); " Stops all playing and paused sounds.");
static PyObject * static PyObject *
@ -231,7 +231,7 @@ Device_stopAll(Device* self)
} }
PyDoc_STRVAR(M_aud_Device_unlock_doc, PyDoc_STRVAR(M_aud_Device_unlock_doc,
".. classmethod:: unlock()\n\n" ".. method:: unlock()\n\n"
" Unlocks the device after a lock call, see :meth:`lock` for\n" " Unlocks the device after a lock call, see :meth:`lock` for\n"
" details."); " details.");

View File

@ -60,7 +60,7 @@ DynamicMusic_dealloc(DynamicMusicP* self)
} }
PyDoc_STRVAR(M_aud_DynamicMusic_addScene_doc, PyDoc_STRVAR(M_aud_DynamicMusic_addScene_doc,
".. classmethod:: addScene(scene)\n\n" ".. method:: addScene(scene)\n\n"
" Adds a new scene.\n\n" " Adds a new scene.\n\n"
" :arg scene: The scene sound.\n" " :arg scene: The scene sound.\n"
" :type scene: :class:`Sound`\n" " :type scene: :class:`Sound`\n"
@ -90,7 +90,7 @@ DynamicMusic_addScene(DynamicMusicP* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_DynamicMusic_addTransition_doc, PyDoc_STRVAR(M_aud_DynamicMusic_addTransition_doc,
".. classmethod:: addTransition(ini, end, transition)\n\n" ".. method:: addTransition(ini, end, transition)\n\n"
" Adds a new scene.\n\n" " Adds a new scene.\n\n"
" :arg ini: the initial scene foor the transition.\n" " :arg ini: the initial scene foor the transition.\n"
" :type ini: int\n" " :type ini: int\n"
@ -125,7 +125,7 @@ DynamicMusic_addTransition(DynamicMusicP* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_DynamicMusic_resume_doc, PyDoc_STRVAR(M_aud_DynamicMusic_resume_doc,
".. classmethod:: resume()\n\n" ".. method:: resume()\n\n"
" Resumes playback of the scene.\n\n" " Resumes playback of the scene.\n\n"
" :return: Whether the action succeeded.\n" " :return: Whether the action succeeded.\n"
" :rtype: bool"); " :rtype: bool");
@ -145,7 +145,7 @@ DynamicMusic_resume(DynamicMusicP* self)
} }
PyDoc_STRVAR(M_aud_DynamicMusic_pause_doc, PyDoc_STRVAR(M_aud_DynamicMusic_pause_doc,
".. classmethod:: pause()\n\n" ".. method:: pause()\n\n"
" Pauses playback of the scene.\n\n" " Pauses playback of the scene.\n\n"
" :return: Whether the action succeeded.\n" " :return: Whether the action succeeded.\n"
" :rtype: bool"); " :rtype: bool");
@ -165,7 +165,7 @@ DynamicMusic_pause(DynamicMusicP* self)
} }
PyDoc_STRVAR(M_aud_DynamicMusic_stop_doc, PyDoc_STRVAR(M_aud_DynamicMusic_stop_doc,
".. classmethod:: stop()\n\n" ".. method:: stop()\n\n"
" Stops playback of the scene.\n\n" " Stops playback of the scene.\n\n"
" :return: Whether the action succeeded.\n" " :return: Whether the action succeeded.\n"
" :rtype: bool\n\n"); " :rtype: bool\n\n");

View File

@ -54,7 +54,7 @@ HRTF_dealloc(HRTFP* self)
} }
PyDoc_STRVAR(M_aud_HRTF_addImpulseResponse_doc, PyDoc_STRVAR(M_aud_HRTF_addImpulseResponse_doc,
".. classmethod:: addImpulseResponseFromSound(sound, azimuth, elevation)\n\n" ".. method:: addImpulseResponseFromSound(sound, azimuth, elevation)\n\n"
" Adds a new hrtf to the HRTF object\n\n" " Adds a new hrtf to the HRTF object\n\n"
" :arg sound: The sound that contains the hrtf.\n" " :arg sound: The sound that contains the hrtf.\n"
" :type sound: :class:`Sound`\n" " :type sound: :class:`Sound`\n"
@ -90,7 +90,7 @@ HRTF_addImpulseResponseFromSound(HRTFP* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_HRTF_loadLeftHrtfSet_doc, PyDoc_STRVAR(M_aud_HRTF_loadLeftHrtfSet_doc,
".. classmethod:: loadLeftHrtfSet(extension, directory)\n\n" ".. method:: loadLeftHrtfSet(extension, directory)\n\n"
" Loads all HRTFs from a directory.\n\n" " Loads all HRTFs from a directory.\n\n"
" :arg extension: The file extension of the hrtfs.\n" " :arg extension: The file extension of the hrtfs.\n"
" :type extension: string\n" " :type extension: string\n"
@ -125,7 +125,7 @@ HRTF_loadLeftHrtfSet(PyTypeObject* type, PyObject* args)
} }
PyDoc_STRVAR(M_aud_HRTF_loadRightHrtfSet_doc, PyDoc_STRVAR(M_aud_HRTF_loadRightHrtfSet_doc,
".. classmethod:: loadLeftHrtfSet(extension, directory)\n\n" ".. method:: loadLeftHrtfSet(extension, directory)\n\n"
" Loads all HRTFs from a directory.\n\n" " Loads all HRTFs from a directory.\n\n"
" :arg extension: The file extension of the hrtfs.\n" " :arg extension: The file extension of the hrtfs.\n"
" :type extension: string\n" " :type extension: string\n"

View File

@ -38,7 +38,7 @@ Handle_dealloc(Handle* self)
} }
PyDoc_STRVAR(M_aud_Handle_pause_doc, PyDoc_STRVAR(M_aud_Handle_pause_doc,
".. classmethod:: pause()\n\n" ".. method:: pause()\n\n"
" Pauses playback.\n\n" " Pauses playback.\n\n"
" :return: Whether the action succeeded.\n" " :return: Whether the action succeeded.\n"
" :rtype: bool"); " :rtype: bool");
@ -58,7 +58,7 @@ Handle_pause(Handle* self)
} }
PyDoc_STRVAR(M_aud_Handle_resume_doc, PyDoc_STRVAR(M_aud_Handle_resume_doc,
".. classmethod:: resume()\n\n" ".. method:: resume()\n\n"
" Resumes playback.\n\n" " Resumes playback.\n\n"
" :return: Whether the action succeeded.\n" " :return: Whether the action succeeded.\n"
" :rtype: bool"); " :rtype: bool");
@ -78,7 +78,7 @@ Handle_resume(Handle* self)
} }
PyDoc_STRVAR(M_aud_Handle_stop_doc, PyDoc_STRVAR(M_aud_Handle_stop_doc,
".. classmethod:: stop()\n\n" ".. method:: stop()\n\n"
" Stops playback.\n\n" " Stops playback.\n\n"
" :return: Whether the action succeeded.\n" " :return: Whether the action succeeded.\n"
" :rtype: bool\n\n" " :rtype: bool\n\n"

View File

@ -60,7 +60,7 @@ PlaybackManager_dealloc(PlaybackManagerP* self)
} }
PyDoc_STRVAR(M_aud_PlaybackManager_play_doc, PyDoc_STRVAR(M_aud_PlaybackManager_play_doc,
".. classmethod:: play(sound, catKey)\n\n" ".. method:: play(sound, catKey)\n\n"
" Plays a sound through the playback manager and assigns it to a category.\n\n" " Plays a sound through the playback manager and assigns it to a category.\n\n"
" :arg sound: The sound to play.\n" " :arg sound: The sound to play.\n"
" :type sound: :class:`Sound`\n" " :type sound: :class:`Sound`\n"
@ -104,7 +104,7 @@ PlaybackManager_play(PlaybackManagerP* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_PlaybackManager_resume_doc, PyDoc_STRVAR(M_aud_PlaybackManager_resume_doc,
".. classmethod:: resume(catKey)\n\n" ".. method:: resume(catKey)\n\n"
" Resumes playback of the catgory.\n\n" " Resumes playback of the catgory.\n\n"
" :arg catKey: the key of the category.\n" " :arg catKey: the key of the category.\n"
" :type catKey: int\n" " :type catKey: int\n"
@ -131,7 +131,7 @@ PlaybackManager_resume(PlaybackManagerP* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_PlaybackManager_pause_doc, PyDoc_STRVAR(M_aud_PlaybackManager_pause_doc,
".. classmethod:: pause(catKey)\n\n" ".. method:: pause(catKey)\n\n"
" Pauses playback of the category.\n\n" " Pauses playback of the category.\n\n"
" :arg catKey: the key of the category.\n" " :arg catKey: the key of the category.\n"
" :type catKey: int\n" " :type catKey: int\n"
@ -158,7 +158,7 @@ PlaybackManager_pause(PlaybackManagerP* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_PlaybackManager_add_category_doc, PyDoc_STRVAR(M_aud_PlaybackManager_add_category_doc,
".. classmethod:: addCategory(volume)\n\n" ".. method:: addCategory(volume)\n\n"
" Adds a category with a custom volume.\n\n" " Adds a category with a custom volume.\n\n"
" :arg volume: The volume for ther new category.\n" " :arg volume: The volume for ther new category.\n"
" :type volume: float\n" " :type volume: float\n"
@ -185,7 +185,7 @@ PlaybackManager_add_category(PlaybackManagerP* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_PlaybackManager_get_volume_doc, PyDoc_STRVAR(M_aud_PlaybackManager_get_volume_doc,
".. classmethod:: getVolume(catKey)\n\n" ".. method:: getVolume(catKey)\n\n"
" Retrieves the volume of a category.\n\n" " Retrieves the volume of a category.\n\n"
" :arg catKey: the key of the category.\n" " :arg catKey: the key of the category.\n"
" :type catKey: int\n" " :type catKey: int\n"
@ -212,7 +212,7 @@ PlaybackManager_get_volume(PlaybackManagerP* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_PlaybackManager_set_volume_doc, PyDoc_STRVAR(M_aud_PlaybackManager_set_volume_doc,
".. classmethod:: setVolume(volume, catKey)\n\n" ".. method:: setVolume(volume, catKey)\n\n"
" Changes the volume of a category.\n\n" " Changes the volume of a category.\n\n"
" :arg volume: the new volume value.\n" " :arg volume: the new volume value.\n"
" :type volume: float\n" " :type volume: float\n"
@ -242,7 +242,7 @@ PlaybackManager_set_volume(PlaybackManagerP* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_PlaybackManager_stop_doc, PyDoc_STRVAR(M_aud_PlaybackManager_stop_doc,
".. classmethod:: stop(catKey)\n\n" ".. method:: stop(catKey)\n\n"
" Stops playback of the category.\n\n" " Stops playback of the category.\n\n"
" :arg catKey: the key of the category.\n" " :arg catKey: the key of the category.\n"
" :type catKey: int\n" " :type catKey: int\n"
@ -269,7 +269,7 @@ PlaybackManager_stop(PlaybackManagerP* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_PlaybackManager_clean_doc, PyDoc_STRVAR(M_aud_PlaybackManager_clean_doc,
".. classmethod:: clean()\n\n" ".. method:: clean()\n\n"
" Cleans all the invalid and finished sound from the playback manager.\n\n"); " Cleans all the invalid and finished sound from the playback manager.\n\n");
static PyObject * static PyObject *

View File

@ -99,7 +99,7 @@ Sequence_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
} }
PyDoc_STRVAR(M_aud_Sequence_add_doc, PyDoc_STRVAR(M_aud_Sequence_add_doc,
".. classmethod:: add()\n\n" ".. method:: add()\n\n"
" Adds a new entry to the sequence.\n\n" " Adds a new entry to the sequence.\n\n"
" :arg sound: The sound this entry should play.\n" " :arg sound: The sound this entry should play.\n"
" :type sound: :class:`Sound`\n" " :type sound: :class:`Sound`\n"
@ -151,7 +151,7 @@ Sequence_add(Sequence* self, PyObject* args, PyObject* kwds)
} }
PyDoc_STRVAR(M_aud_Sequence_remove_doc, PyDoc_STRVAR(M_aud_Sequence_remove_doc,
".. classmethod:: remove()\n\n" ".. method:: remove()\n\n"
" Removes an entry from the sequence.\n\n" " Removes an entry from the sequence.\n\n"
" :arg entry: The entry to remove.\n" " :arg entry: The entry to remove.\n"
" :type entry: :class:`SequenceEntry`\n"); " :type entry: :class:`SequenceEntry`\n");
@ -183,7 +183,7 @@ Sequence_remove(Sequence* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sequence_setAnimationData_doc, PyDoc_STRVAR(M_aud_Sequence_setAnimationData_doc,
".. classmethod:: setAnimationData()\n\n" ".. method:: setAnimationData()\n\n"
" Writes animation data to a sequence.\n\n" " Writes animation data to a sequence.\n\n"
" :arg type: The type of animation data.\n" " :arg type: The type of animation data.\n"
" :type type: int\n" " :type type: int\n"

View File

@ -43,7 +43,7 @@ SequenceEntry_dealloc(SequenceEntry* self)
} }
PyDoc_STRVAR(M_aud_SequenceEntry_move_doc, PyDoc_STRVAR(M_aud_SequenceEntry_move_doc,
".. classmethod:: move()\n\n" ".. method:: move()\n\n"
" Moves the entry.\n\n" " Moves the entry.\n\n"
" :arg begin: The new start time.\n" " :arg begin: The new start time.\n"
" :type begin: double\n" " :type begin: double\n"
@ -73,7 +73,7 @@ SequenceEntry_move(SequenceEntry* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_SequenceEntry_setAnimationData_doc, PyDoc_STRVAR(M_aud_SequenceEntry_setAnimationData_doc,
".. classmethod:: setAnimationData()\n\n" ".. method:: setAnimationData()\n\n"
" Writes animation data to a sequenced entry.\n\n" " Writes animation data to a sequenced entry.\n\n"
" :arg type: The type of animation data.\n" " :arg type: The type of animation data.\n"
" :type type: int\n" " :type type: int\n"

View File

@ -115,7 +115,7 @@ Sound_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
} }
PyDoc_STRVAR(M_aud_Sound_data_doc, PyDoc_STRVAR(M_aud_Sound_data_doc,
".. classmethod:: data()\n\n" ".. method:: data()\n\n"
" Retrieves the data of the sound as numpy array.\n\n" " Retrieves the data of the sound as numpy array.\n\n"
" :return: A two dimensional numpy float array.\n" " :return: A two dimensional numpy float array.\n"
" :rtype: :class:`numpy.ndarray`\n\n" " :rtype: :class:`numpy.ndarray`\n\n"
@ -146,7 +146,7 @@ Sound_data(Sound* self)
} }
PyDoc_STRVAR(M_aud_Sound_write_doc, PyDoc_STRVAR(M_aud_Sound_write_doc,
".. classmethod:: write(filename, rate, channels, format, container, codec, bitrate, buffersize)\n\n" ".. method:: write(filename, rate, channels, format, container, codec, bitrate, buffersize)\n\n"
" Writes the sound to a file.\n\n" " Writes the sound to a file.\n\n"
" :arg filename: The path to write to.\n" " :arg filename: The path to write to.\n"
" :type filename: string\n" " :type filename: string\n"
@ -357,7 +357,7 @@ Sound_buffer(PyTypeObject* type, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_cache_doc, PyDoc_STRVAR(M_aud_Sound_cache_doc,
".. classmethod:: cache()\n\n" ".. method:: cache()\n\n"
" Caches a sound into RAM.\n\n" " Caches a sound into RAM.\n\n"
" This saves CPU usage needed for decoding and file access if the\n" " This saves CPU usage needed for decoding and file access if the\n"
" underlying sound reads from a file on the harddisk,\n" " underlying sound reads from a file on the harddisk,\n"
@ -631,7 +631,7 @@ Sound_triangle(PyTypeObject* type, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_accumulate_doc, PyDoc_STRVAR(M_aud_Sound_accumulate_doc,
".. classmethod:: accumulate(additive=False)\n\n" ".. method:: accumulate(additive=False)\n\n"
" Accumulates a sound by summing over positive input\n" " Accumulates a sound by summing over positive input\n"
" differences thus generating a monotonic sigal.\n" " differences thus generating a monotonic sigal.\n"
" If additivity is set to true negative input differences get added too,\n" " If additivity is set to true negative input differences get added too,\n"
@ -683,7 +683,7 @@ Sound_accumulate(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_ADSR_doc, PyDoc_STRVAR(M_aud_Sound_ADSR_doc,
".. classmethod:: ADSR(attack, decay, sustain, release)\n\n" ".. method:: ADSR(attack, decay, sustain, release)\n\n"
" Attack-Decay-Sustain-Release envelopes the volume of a sound.\n" " Attack-Decay-Sustain-Release envelopes the volume of a sound.\n"
" Note: there is currently no way to trigger the release with this API.\n\n" " Note: there is currently no way to trigger the release with this API.\n\n"
" :arg attack: The attack time in seconds.\n" " :arg attack: The attack time in seconds.\n"
@ -726,7 +726,7 @@ Sound_ADSR(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_delay_doc, PyDoc_STRVAR(M_aud_Sound_delay_doc,
".. classmethod:: delay(time)\n\n" ".. method:: delay(time)\n\n"
" Delays by playing adding silence in front of the other sound's data.\n\n" " Delays by playing adding silence in front of the other sound's data.\n\n"
" :arg time: How many seconds of silence should be added before the sound.\n" " :arg time: How many seconds of silence should be added before the sound.\n"
" :type time: float\n" " :type time: float\n"
@ -762,7 +762,7 @@ Sound_delay(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_envelope_doc, PyDoc_STRVAR(M_aud_Sound_envelope_doc,
".. classmethod:: envelope(attack, release, threshold, arthreshold)\n\n" ".. method:: envelope(attack, release, threshold, arthreshold)\n\n"
" Delays by playing adding silence in front of the other sound's data.\n\n" " Delays by playing adding silence in front of the other sound's data.\n\n"
" :arg attack: The attack factor.\n" " :arg attack: The attack factor.\n"
" :type attack: float\n" " :type attack: float\n"
@ -804,7 +804,7 @@ Sound_envelope(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_fadein_doc, PyDoc_STRVAR(M_aud_Sound_fadein_doc,
".. classmethod:: fadein(start, length)\n\n" ".. method:: fadein(start, length)\n\n"
" Fades a sound in by raising the volume linearly in the given\n" " Fades a sound in by raising the volume linearly in the given\n"
" time interval.\n\n" " time interval.\n\n"
" :arg start: Time in seconds when the fading should start.\n" " :arg start: Time in seconds when the fading should start.\n"
@ -844,7 +844,7 @@ Sound_fadein(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_fadeout_doc, PyDoc_STRVAR(M_aud_Sound_fadeout_doc,
".. classmethod:: fadeout(start, length)\n\n" ".. method:: fadeout(start, length)\n\n"
" Fades a sound in by lowering the volume linearly in the given\n" " Fades a sound in by lowering the volume linearly in the given\n"
" time interval.\n\n" " time interval.\n\n"
" :arg start: Time in seconds when the fading should start.\n" " :arg start: Time in seconds when the fading should start.\n"
@ -886,7 +886,7 @@ Sound_fadeout(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_filter_doc, PyDoc_STRVAR(M_aud_Sound_filter_doc,
".. classmethod:: filter(b, a = (1))\n\n" ".. method:: filter(b, a = (1))\n\n"
" Filters a sound with the supplied IIR filter coefficients.\n" " Filters a sound with the supplied IIR filter coefficients.\n"
" Without the second parameter you'll get a FIR filter.\n\n" " Without the second parameter you'll get a FIR filter.\n\n"
" If the first value of the a sequence is 0,\n" " If the first value of the a sequence is 0,\n"
@ -986,7 +986,7 @@ Sound_filter(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_highpass_doc, PyDoc_STRVAR(M_aud_Sound_highpass_doc,
".. classmethod:: highpass(frequency, Q=0.5)\n\n" ".. method:: highpass(frequency, Q=0.5)\n\n"
" Creates a second order highpass filter based on the transfer\n" " Creates a second order highpass filter based on the transfer\n"
" function :math:`H(s) = s^2 / (s^2 + s/Q + 1)`\n\n" " function :math:`H(s) = s^2 / (s^2 + s/Q + 1)`\n\n"
" :arg frequency: The cut off trequency of the highpass.\n" " :arg frequency: The cut off trequency of the highpass.\n"
@ -1026,7 +1026,7 @@ Sound_highpass(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_limit_doc, PyDoc_STRVAR(M_aud_Sound_limit_doc,
".. classmethod:: limit(start, end)\n\n" ".. method:: limit(start, end)\n\n"
" Limits a sound within a specific start and end time.\n\n" " Limits a sound within a specific start and end time.\n\n"
" :arg start: Start time in seconds.\n" " :arg start: Start time in seconds.\n"
" :type start: float\n" " :type start: float\n"
@ -1064,7 +1064,7 @@ Sound_limit(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_loop_doc, PyDoc_STRVAR(M_aud_Sound_loop_doc,
".. classmethod:: loop(count)\n\n" ".. method:: loop(count)\n\n"
" Loops a sound.\n\n" " Loops a sound.\n\n"
" :arg count: How often the sound should be looped.\n" " :arg count: How often the sound should be looped.\n"
" Negative values mean endlessly.\n" " Negative values mean endlessly.\n"
@ -1104,7 +1104,7 @@ Sound_loop(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_lowpass_doc, PyDoc_STRVAR(M_aud_Sound_lowpass_doc,
".. classmethod:: lowpass(frequency, Q=0.5)\n\n" ".. method:: lowpass(frequency, Q=0.5)\n\n"
" Creates a second order lowpass filter based on the transfer " " Creates a second order lowpass filter based on the transfer "
" function :math:`H(s) = 1 / (s^2 + s/Q + 1)`\n\n" " function :math:`H(s) = 1 / (s^2 + s/Q + 1)`\n\n"
" :arg frequency: The cut off trequency of the lowpass.\n" " :arg frequency: The cut off trequency of the lowpass.\n"
@ -1144,7 +1144,7 @@ Sound_lowpass(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_modulate_doc, PyDoc_STRVAR(M_aud_Sound_modulate_doc,
".. classmethod:: modulate(sound)\n\n" ".. method:: modulate(sound)\n\n"
" Modulates two factories.\n\n" " Modulates two factories.\n\n"
" :arg sound: The sound to modulate over the other.\n" " :arg sound: The sound to modulate over the other.\n"
" :type sound: :class:`Sound`\n" " :type sound: :class:`Sound`\n"
@ -1186,7 +1186,7 @@ Sound_modulate(Sound* self, PyObject* object)
} }
PyDoc_STRVAR(M_aud_Sound_pitch_doc, PyDoc_STRVAR(M_aud_Sound_pitch_doc,
".. classmethod:: pitch(factor)\n\n" ".. method:: pitch(factor)\n\n"
" Changes the pitch of a sound with a specific factor.\n\n" " Changes the pitch of a sound with a specific factor.\n\n"
" :arg factor: The factor to change the pitch with.\n" " :arg factor: The factor to change the pitch with.\n"
" :type factor: float\n" " :type factor: float\n"
@ -1229,7 +1229,7 @@ Sound_pitch(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_rechannel_doc, PyDoc_STRVAR(M_aud_Sound_rechannel_doc,
".. classmethod:: rechannel(channels)\n\n" ".. method:: rechannel(channels)\n\n"
" Rechannels the sound.\n\n" " Rechannels the sound.\n\n"
" :arg channels: The new channel configuration.\n" " :arg channels: The new channel configuration.\n"
" :type channels: int\n" " :type channels: int\n"
@ -1269,7 +1269,7 @@ Sound_rechannel(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_resample_doc, PyDoc_STRVAR(M_aud_Sound_resample_doc,
".. classmethod:: resample(rate, high_quality)\n\n" ".. method:: resample(rate, high_quality)\n\n"
" Resamples the sound.\n\n" " Resamples the sound.\n\n"
" :arg rate: The new sample rate.\n" " :arg rate: The new sample rate.\n"
" :type rate: double\n" " :type rate: double\n"
@ -1324,7 +1324,7 @@ Sound_resample(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_reverse_doc, PyDoc_STRVAR(M_aud_Sound_reverse_doc,
".. classmethod:: reverse()\n\n" ".. method:: reverse()\n\n"
" Plays a sound reversed.\n\n" " Plays a sound reversed.\n\n"
" :return: The created :class:`Sound` object.\n" " :return: The created :class:`Sound` object.\n"
" :rtype: :class:`Sound`\n\n" " :rtype: :class:`Sound`\n\n"
@ -1362,7 +1362,7 @@ Sound_reverse(Sound* self)
} }
PyDoc_STRVAR(M_aud_Sound_sum_doc, PyDoc_STRVAR(M_aud_Sound_sum_doc,
".. classmethod:: sum()\n\n" ".. method:: sum()\n\n"
" Sums the samples of a sound.\n\n" " Sums the samples of a sound.\n\n"
" :return: The created :class:`Sound` object.\n" " :return: The created :class:`Sound` object.\n"
" :rtype: :class:`Sound`"); " :rtype: :class:`Sound`");
@ -1391,7 +1391,7 @@ Sound_sum(Sound* self)
} }
PyDoc_STRVAR(M_aud_Sound_threshold_doc, PyDoc_STRVAR(M_aud_Sound_threshold_doc,
".. classmethod:: threshold(threshold = 0)\n\n" ".. method:: threshold(threshold = 0)\n\n"
" Makes a threshold wave out of an audio wave by setting all samples\n" " Makes a threshold wave out of an audio wave by setting all samples\n"
" with a amplitude >= threshold to 1, all <= -threshold to -1 and\n" " with a amplitude >= threshold to 1, all <= -threshold to -1 and\n"
" all between to 0.\n\n" " all between to 0.\n\n"
@ -1430,7 +1430,7 @@ Sound_threshold(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_volume_doc, PyDoc_STRVAR(M_aud_Sound_volume_doc,
".. classmethod:: volume(volume)\n\n" ".. method:: volume(volume)\n\n"
" Changes the volume of a sound.\n\n" " Changes the volume of a sound.\n\n"
" :arg volume: The new volume..\n" " :arg volume: The new volume..\n"
" :type volume: float\n" " :type volume: float\n"
@ -1471,7 +1471,7 @@ Sound_volume(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_join_doc, PyDoc_STRVAR(M_aud_Sound_join_doc,
".. classmethod:: join(sound)\n\n" ".. method:: join(sound)\n\n"
" Plays two factories in sequence.\n\n" " Plays two factories in sequence.\n\n"
" :arg sound: The sound to play second.\n" " :arg sound: The sound to play second.\n"
" :type sound: :class:`Sound`\n" " :type sound: :class:`Sound`\n"
@ -1514,7 +1514,7 @@ Sound_join(Sound* self, PyObject* object)
} }
PyDoc_STRVAR(M_aud_Sound_mix_doc, PyDoc_STRVAR(M_aud_Sound_mix_doc,
".. classmethod:: mix(sound)\n\n" ".. method:: mix(sound)\n\n"
" Mixes two factories.\n\n" " Mixes two factories.\n\n"
" :arg sound: The sound to mix over the other.\n" " :arg sound: The sound to mix over the other.\n"
" :type sound: :class:`Sound`\n" " :type sound: :class:`Sound`\n"
@ -1556,7 +1556,7 @@ Sound_mix(Sound* self, PyObject* object)
} }
PyDoc_STRVAR(M_aud_Sound_pingpong_doc, PyDoc_STRVAR(M_aud_Sound_pingpong_doc,
".. classmethod:: pingpong()\n\n" ".. method:: pingpong()\n\n"
" Plays a sound forward and then backward.\n" " Plays a sound forward and then backward.\n"
" This is like joining a sound with its reverse.\n\n" " This is like joining a sound with its reverse.\n\n"
" :return: The created :class:`Sound` object.\n" " :return: The created :class:`Sound` object.\n"
@ -1622,7 +1622,7 @@ Sound_list(PyTypeObject* type, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_mutable_doc, PyDoc_STRVAR(M_aud_Sound_mutable_doc,
".. classmethod:: mutable()\n\n" ".. method:: mutable()\n\n"
" Creates a sound that will be restarted when sought backwards.\n" " Creates a sound that will be restarted when sought backwards.\n"
" If the original sound is a sound list, the playing sound can change.\n\n" " If the original sound is a sound list, the playing sound can change.\n\n"
" :return: The created :class:`Sound` object.\n" " :return: The created :class:`Sound` object.\n"
@ -1652,7 +1652,7 @@ Sound_mutable(Sound* self)
} }
PyDoc_STRVAR(M_aud_Sound_list_addSound_doc, PyDoc_STRVAR(M_aud_Sound_list_addSound_doc,
".. classmethod:: addSound(sound)\n\n" ".. method:: addSound(sound)\n\n"
" Adds a new sound to a sound list.\n\n" " Adds a new sound to a sound list.\n\n"
" :arg sound: The sound that will be added to the list.\n" " :arg sound: The sound that will be added to the list.\n"
" :type sound: :class:`Sound`\n\n" " :type sound: :class:`Sound`\n\n"
@ -1685,7 +1685,7 @@ Sound_list_addSound(Sound* self, PyObject* object)
#ifdef WITH_CONVOLUTION #ifdef WITH_CONVOLUTION
PyDoc_STRVAR(M_aud_Sound_convolver_doc, PyDoc_STRVAR(M_aud_Sound_convolver_doc,
".. classmethod:: convolver()\n\n" ".. method:: convolver()\n\n"
" Creates a sound that will apply convolution to another sound.\n\n" " Creates a sound that will apply convolution to another sound.\n\n"
" :arg impulseResponse: The filter with which convolve the sound.\n" " :arg impulseResponse: The filter with which convolve the sound.\n"
" :type impulseResponse: :class:`ImpulseResponse`\n" " :type impulseResponse: :class:`ImpulseResponse`\n"
@ -1734,7 +1734,7 @@ Sound_convolver(Sound* self, PyObject* args)
} }
PyDoc_STRVAR(M_aud_Sound_binaural_doc, PyDoc_STRVAR(M_aud_Sound_binaural_doc,
".. classmethod:: convolver()\n\n" ".. method:: binaural()\n\n"
" Creates a binaural sound using another sound as source. The original sound must be mono\n\n" " Creates a binaural sound using another sound as source. The original sound must be mono\n\n"
" :arg hrtfs: An HRTF set.\n" " :arg hrtfs: An HRTF set.\n"
" :type hrtf: :class:`HRTF`\n" " :type hrtf: :class:`HRTF`\n"

View File

@ -2446,6 +2446,14 @@ def draw_pause(self, context):
layout.prop(cscene, "preview_pause", icon='PLAY' if cscene.preview_pause else 'PAUSE', text="") layout.prop(cscene, "preview_pause", icon='PLAY' if cscene.preview_pause else 'PAUSE', text="")
def draw_make_links(self, context):
if context.engine == "CYCLES":
layout = self.layout
layout.separator()
layout.operator_menu_enum("object.light_linking_receivers_link", "link_state")
layout.operator_menu_enum("object.light_linking_blockers_link", "link_state")
def get_panels(): def get_panels():
exclude_panels = { exclude_panels = {
'DATA_PT_camera_dof', 'DATA_PT_camera_dof',
@ -2584,6 +2592,7 @@ def register():
bpy.types.RENDER_PT_context.append(draw_device) bpy.types.RENDER_PT_context.append(draw_device)
bpy.types.VIEW3D_HT_header.append(draw_pause) bpy.types.VIEW3D_HT_header.append(draw_pause)
bpy.types.VIEW3D_MT_make_links.append(draw_make_links)
for panel in get_panels(): for panel in get_panels():
panel.COMPAT_ENGINES.add('CYCLES') panel.COMPAT_ENGINES.add('CYCLES')
@ -2597,6 +2606,7 @@ def unregister():
bpy.types.RENDER_PT_context.remove(draw_device) bpy.types.RENDER_PT_context.remove(draw_device)
bpy.types.VIEW3D_HT_header.remove(draw_pause) bpy.types.VIEW3D_HT_header.remove(draw_pause)
bpy.types.VIEW3D_MT_make_links.remove(draw_make_links)
for panel in get_panels(): for panel in get_panels():
if 'CYCLES' in panel.COMPAT_ENGINES: if 'CYCLES' in panel.COMPAT_ENGINES:

View File

@ -49,7 +49,7 @@ ccl_device int shadow_linking_pick_mesh_intersection(KernelGlobals kg,
} }
/* Only record primitives that potentially have emission. /* Only record primitives that potentially have emission.
* TODO: optimize with a dedicated ray visiblity flag, which could then also be * TODO: optimize with a dedicated ray visibility flag, which could then also be
* used once lights are in the BVH as geometry? */ * used once lights are in the BVH as geometry? */
const int shader = intersection_get_shader(kg, &current_isect); const int shader = intersection_get_shader(kg, &current_isect);
const int shader_flags = kernel_data_fetch(shaders, shader).flags; const int shader_flags = kernel_data_fetch(shaders, shader).flags;

View File

@ -483,12 +483,7 @@ ccl_device_forceinline bool mnee_newton_solver(KernelGlobals kg,
if (!hit) if (!hit)
break; break;
// TODO: Is the fetch needed here? The shade_surface simply reads isect->object. if (projection_isect.object == mv.object) {
int hit_object = (projection_isect.object == OBJECT_NONE) ?
kernel_data_fetch(prim_object, projection_isect.prim) :
projection_isect.object;
if (hit_object == mv.object) {
projection_success = true; projection_success = true;
break; break;
} }
@ -778,9 +773,8 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
/* Initialize throughput and evaluate receiver bsdf * |n.wo|. */ /* Initialize throughput and evaluate receiver bsdf * |n.wo|. */
surface_shader_bsdf_eval(kg, state, sd, wo, throughput, ls->shader); surface_shader_bsdf_eval(kg, state, sd, wo, throughput, ls->shader);
/* Update light sample with new position / direct.ion /* Update light sample with new position / direction and keep pdf in vertex area measure. */
* and keep pdf in vertex area measure */ light_sample_update(kg, ls, vertices[vertex_count - 1].p);
light_sample_update_position(kg, ls, vertices[vertex_count - 1].p);
/* Save state path bounce info in case a light path node is used in the refractive interface or /* Save state path bounce info in case a light path node is used in the refractive interface or
* light shader graph. */ * light shader graph. */

View File

@ -140,7 +140,9 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg,
#endif #endif
#ifdef __LIGHT_LINKING__ #ifdef __LIGHT_LINKING__
if (!light_link_light_match(kg, light_link_receiver_forward(kg, state), lamp)) { if (!light_link_light_match(kg, light_link_receiver_forward(kg, state), lamp) &&
!(path_flag & PATH_RAY_CAMERA))
{
continue; continue;
} }
#endif #endif

View File

@ -4,9 +4,12 @@
#pragma once #pragma once
#include "kernel/integrator/path_state.h" #include "kernel/integrator/path_state.h"
#include "kernel/integrator/shade_surface.h"
#include "kernel/light/distant.h" #include "kernel/light/distant.h"
#include "kernel/light/light.h" #include "kernel/light/light.h"
#include "kernel/light/sample.h"
#include "kernel/integrator/shade_surface.h"
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN

View File

@ -10,6 +10,8 @@
#include "kernel/film/denoising_passes.h" #include "kernel/film/denoising_passes.h"
#include "kernel/film/light_passes.h" #include "kernel/film/light_passes.h"
#include "kernel/light/sample.h"
#include "kernel/integrator/mnee.h" #include "kernel/integrator/mnee.h"
#include "kernel/integrator/guiding.h" #include "kernel/integrator/guiding.h"
@ -17,8 +19,6 @@
#include "kernel/integrator/subsurface.h" #include "kernel/integrator/subsurface.h"
#include "kernel/integrator/volume_stack.h" #include "kernel/integrator/volume_stack.h"
#include "kernel/light/sample.h"
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
ccl_device_forceinline void integrate_surface_shader_setup(KernelGlobals kg, ccl_device_forceinline void integrate_surface_shader_setup(KernelGlobals kg,
@ -113,14 +113,16 @@ ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg,
ccl_global float *ccl_restrict ccl_global float *ccl_restrict
render_buffer) render_buffer)
{ {
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
#ifdef __LIGHT_LINKING__ #ifdef __LIGHT_LINKING__
if (!light_link_object_match(kg, light_link_receiver_forward(kg, state), sd->object)) { if (!light_link_object_match(kg, light_link_receiver_forward(kg, state), sd->object) &&
!(path_flag & PATH_RAY_CAMERA))
{
return; return;
} }
#endif #endif
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
#ifdef __SHADOW_LINKING__ #ifdef __SHADOW_LINKING__
/* Indirect emission of shadow-linked emissive surfaces is done via shadow rays to dedicated /* Indirect emission of shadow-linked emissive surfaces is done via shadow rays to dedicated
* light sources. */ * light sources. */
@ -284,8 +286,8 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
const bool is_transmission = dot(ls.D, sd->N) < 0.0f; const bool is_transmission = dot(ls.D, sd->N) < 0.0f;
#ifdef __MNEE__
int mnee_vertex_count = 0; int mnee_vertex_count = 0;
#ifdef __MNEE__
IF_KERNEL_FEATURE(MNEE) IF_KERNEL_FEATURE(MNEE)
{ {
if (ls.lamp != LAMP_NONE) { if (ls.lamp != LAMP_NONE) {

View File

@ -95,9 +95,9 @@ ccl_device_inline void surface_shader_prepare_guiding(KernelGlobals kg,
bssrdf_sampling_fraction /= bsdf_bssrdf_sampling_sum; bssrdf_sampling_fraction /= bsdf_bssrdf_sampling_sum;
} }
/* Init guiding */ /* Initial guiding */
/* The the roughness because the function returns alpha.x * alpha.y. In addition alpha is squared /* The roughness because the function returns `alpha.x * alpha.y`.
* again */ * In addition alpha is squared again. */
float avg_roughness = surface_shader_average_sample_weight_squared_roughness(sd); float avg_roughness = surface_shader_average_sample_weight_squared_roughness(sd);
avg_roughness = safe_sqrtf(avg_roughness); avg_roughness = safe_sqrtf(avg_roughness);
if (!fully_opaque || avg_roughness < guiding_roughness_threshold || if (!fully_opaque || avg_roughness < guiding_roughness_threshold ||

View File

@ -347,9 +347,9 @@ ccl_device_inline bool area_light_sample(const ccl_global KernelLight *klight,
return true; return true;
} }
ccl_device_forceinline void area_light_update_position(const ccl_global KernelLight *klight, ccl_device_forceinline void area_light_mnee_sample_update(const ccl_global KernelLight *klight,
ccl_private LightSample *ls, ccl_private LightSample *ls,
const float3 P) const float3 P)
{ {
if (klight->area.tan_half_spread == 0) { if (klight->area.tan_half_spread == 0) {
/* Update position on the light to keep the direction fixed. */ /* Update position on the light to keep the direction fixed. */

View File

@ -54,8 +54,7 @@ ccl_device float3 background_map_sample(KernelGlobals kg, float2 rand, ccl_priva
int middle = first + step; int middle = first + step;
if (kernel_data_fetch(light_background_conditional_cdf, index_v * cdf_width + middle).y < if (kernel_data_fetch(light_background_conditional_cdf, index_v * cdf_width + middle).y <
rand.x) rand.x) {
{
first = middle + 1; first = middle + 1;
count -= step + 1; count -= step + 1;
} }

View File

@ -311,7 +311,7 @@ ccl_device_forceinline int lights_intersect_impl(KernelGlobals kg,
#ifdef __LIGHT_LINKING__ #ifdef __LIGHT_LINKING__
/* Light linking. */ /* Light linking. */
if (!light_link_light_match(kg, receiver_forward, lamp)) { if (!light_link_light_match(kg, receiver_forward, lamp) && !(path_flag & PATH_RAY_CAMERA)) {
continue; continue;
} }
#endif #endif
@ -484,23 +484,4 @@ ccl_device bool light_sample_from_intersection(KernelGlobals kg,
return true; return true;
} }
/* Update light sample for changed new position, for MNEE. */
ccl_device_forceinline void light_update_position(KernelGlobals kg,
ccl_private LightSample *ls,
const float3 P)
{
const ccl_global KernelLight *klight = &kernel_data_fetch(lights, ls->lamp);
if (ls->type == LIGHT_POINT) {
point_light_update_position(klight, ls, P);
}
else if (ls->type == LIGHT_SPOT) {
spot_light_update_position(klight, ls, P);
}
else if (ls->type == LIGHT_AREA) {
area_light_update_position(klight, ls, P);
}
}
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@ -29,9 +29,6 @@ ccl_device_inline bool point_light_sample(const ccl_global KernelLight *klight,
ls->Ng = -ls->D; ls->Ng = -ls->D;
ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea; ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea;
if (!in_volume_segment && ls->eval_fac == 0.0f) {
return false;
}
float2 uv = map_to_sphere(ls->Ng); float2 uv = map_to_sphere(ls->Ng);
ls->u = uv.x; ls->u = uv.x;
@ -40,9 +37,9 @@ ccl_device_inline bool point_light_sample(const ccl_global KernelLight *klight,
return true; return true;
} }
ccl_device_forceinline void point_light_update_position(const ccl_global KernelLight *klight, ccl_device_forceinline void point_light_mnee_sample_update(const ccl_global KernelLight *klight,
ccl_private LightSample *ls, ccl_private LightSample *ls,
const float3 P) const float3 P)
{ {
ls->D = normalize_len(ls->P - P, &ls->t); ls->D = normalize_len(ls->P - P, &ls->t);
ls->Ng = -ls->D; ls->Ng = -ls->D;
@ -53,6 +50,7 @@ ccl_device_forceinline void point_light_update_position(const ccl_global KernelL
float invarea = klight->spot.invarea; float invarea = klight->spot.invarea;
ls->eval_fac = (0.25f * M_1_PI_F) * invarea; ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
/* NOTE : preserve pdf in area measure. */
ls->pdf = invarea; ls->pdf = invarea;
} }
@ -89,10 +87,6 @@ ccl_device_inline bool point_light_sample_from_intersection(
ls->eval_fac = (0.25f * M_1_PI_F) * invarea; ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
ls->pdf = invarea; ls->pdf = invarea;
if (ls->eval_fac == 0.0f) {
return false;
}
float2 uv = map_to_sphere(ls->Ng); float2 uv = map_to_sphere(ls->Ng);
ls->u = uv.x; ls->u = uv.x;
ls->v = uv.y; ls->v = uv.y;

View File

@ -366,15 +366,26 @@ ccl_device bool light_sample_from_position(KernelGlobals kg,
} }
} }
ccl_device_forceinline void light_sample_update_position(KernelGlobals kg, /* Update light sample with new shading point position for MNEE. The position on the light is fixed
ccl_private LightSample *ls, * except for directional light. */
const float3 P) ccl_device_forceinline void light_sample_update(KernelGlobals kg,
ccl_private LightSample *ls,
const float3 P)
{ {
/* Update light sample for new shading point position, while keeping const ccl_global KernelLight *klight = &kernel_data_fetch(lights, ls->lamp);
* position on the light fixed. */
/* NOTE : preserve pdf in area measure. */ if (ls->type == LIGHT_POINT) {
light_update_position(kg, ls, P); point_light_mnee_sample_update(klight, ls, P);
}
else if (ls->type == LIGHT_SPOT) {
spot_light_mnee_sample_update(klight, ls, P);
}
else if (ls->type == LIGHT_AREA) {
area_light_mnee_sample_update(klight, ls, P);
}
else {
/* Keep previous values. */
}
/* Re-apply already computed selection pdf. */ /* Re-apply already computed selection pdf. */
ls->pdf *= ls->pdf_selection; ls->pdf *= ls->pdf_selection;

View File

@ -58,9 +58,9 @@ ccl_device_inline bool spot_light_sample(const ccl_global KernelLight *klight,
return true; return true;
} }
ccl_device_forceinline void spot_light_update_position(const ccl_global KernelLight *klight, ccl_device_forceinline void spot_light_mnee_sample_update(const ccl_global KernelLight *klight,
ccl_private LightSample *ls, ccl_private LightSample *ls,
const float3 P) const float3 P)
{ {
ls->D = normalize_len(ls->P - P, &ls->t); ls->D = normalize_len(ls->P - P, &ls->t);
ls->Ng = -ls->D; ls->Ng = -ls->D;
@ -71,6 +71,7 @@ ccl_device_forceinline void spot_light_update_position(const ccl_global KernelLi
float invarea = klight->spot.invarea; float invarea = klight->spot.invarea;
ls->eval_fac = (0.25f * M_1_PI_F) * invarea; ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
/* NOTE : preserve pdf in area measure. */
ls->pdf = invarea; ls->pdf = invarea;
/* spot light attenuation */ /* spot light attenuation */

View File

@ -25,6 +25,8 @@
# define HAVE_MALLOC_STATS # define HAVE_MALLOC_STATS
#elif defined(__FreeBSD__) #elif defined(__FreeBSD__)
# include <malloc_np.h> # include <malloc_np.h>
#elif defined(__OpenBSD__)
# undef USE_MALLOC_USABLE_SIZE
#elif defined(__APPLE__) #elif defined(__APPLE__)
# include <malloc/malloc.h> # include <malloc/malloc.h>
# define malloc_usable_size malloc_size # define malloc_usable_size malloc_size

View File

@ -362,7 +362,14 @@ def load():
use_v3d_tab_menu=kc_prefs.use_v3d_tab_menu, use_v3d_tab_menu=kc_prefs.use_v3d_tab_menu,
use_v3d_shade_ex_pie=kc_prefs.use_v3d_shade_ex_pie, use_v3d_shade_ex_pie=kc_prefs.use_v3d_shade_ex_pie,
use_gizmo_drag=(is_select_left and kc_prefs.gizmo_action == 'DRAG'), use_gizmo_drag=(is_select_left and kc_prefs.gizmo_action == 'DRAG'),
use_fallback_tool=True if is_select_left else (kc_prefs.rmb_action == 'FALLBACK_TOOL'), use_fallback_tool=True,
use_fallback_tool_select_handled=(
# LMB doesn't need additional selection fallback key-map items.
False if is_select_left else
# RMB is select and RMB must trigger the fallback tool.
# Otherwise LMB activates the fallback tool and RMB always tweak-selects.
(kc_prefs.rmb_action != 'FALLBACK_TOOL')
),
use_tweak_select_passthrough=(show_developer_ui and kc_prefs.use_tweak_select_passthrough), use_tweak_select_passthrough=(show_developer_ui and kc_prefs.use_tweak_select_passthrough),
use_tweak_tool_lmb_interaction=( use_tweak_tool_lmb_interaction=(
False if is_select_left else False if is_select_left else

View File

@ -52,6 +52,8 @@ class Params:
"use_gizmo_drag", "use_gizmo_drag",
# Use the fallback tool instead of tweak for RMB select. # Use the fallback tool instead of tweak for RMB select.
"use_fallback_tool", "use_fallback_tool",
# Selection actions are already accounted for, no need to add additional selection keys.
"use_fallback_tool_select_handled",
# Use pie menu for tab by default (swap 'Tab/Ctrl-Tab'). # Use pie menu for tab by default (swap 'Tab/Ctrl-Tab').
"use_v3d_tab_menu", "use_v3d_tab_menu",
# Use extended pie menu for shading. # Use extended pie menu for shading.
@ -78,7 +80,7 @@ class Params:
# The fallback tool is activated on the same button as selection. # The fallback tool is activated on the same button as selection.
# Shorthand for: `(True if (select_mouse == 'LEFT') else self.use_fallback_tool)` # Shorthand for: `(True if (select_mouse == 'LEFT') else self.use_fallback_tool)`
"use_fallback_tool_select_mouse", "use_fallback_tool_select_mouse",
# Shorthand for: `('CLICK' if self.use_fallback_tool and select_mouse == 'RIGHT' else self.select_mouse_value)`. # Shorthand for: `(self.select_mouse_value if self.use_fallback_tool_select_handled else 'CLICK')`.
"select_mouse_value_fallback", "select_mouse_value_fallback",
# Shorthand for: `{"type": params.select_mouse, "value": 'CLICK_DRAG'}`. # Shorthand for: `{"type": params.select_mouse, "value": 'CLICK_DRAG'}`.
"select_tweak_event", "select_tweak_event",
@ -112,6 +114,7 @@ class Params:
use_select_all_toggle=False, use_select_all_toggle=False,
use_gizmo_drag=True, use_gizmo_drag=True,
use_fallback_tool=False, use_fallback_tool=False,
use_fallback_tool_select_handled=True,
use_tweak_select_passthrough=False, use_tweak_select_passthrough=False,
use_tweak_tool_lmb_interaction=False, use_tweak_tool_lmb_interaction=False,
use_v3d_tab_menu=False, use_v3d_tab_menu=False,
@ -207,9 +210,17 @@ class Params:
self.use_fallback_tool = use_fallback_tool self.use_fallback_tool = use_fallback_tool
# Convenience variables: # Convenience variables:
self.use_fallback_tool_select_mouse = True if (select_mouse == 'LEFT') else self.use_fallback_tool self.use_fallback_tool_select_handled = (
True if (select_mouse == 'LEFT') else
use_fallback_tool_select_handled
)
self.use_fallback_tool_select_mouse = (
True if (select_mouse == 'LEFT') else
(not self.use_fallback_tool_select_handled)
)
self.select_mouse_value_fallback = ( self.select_mouse_value_fallback = (
'CLICK' if (self.use_fallback_tool and select_mouse == 'RIGHT') else self.select_mouse_value self.select_mouse_value if self.use_fallback_tool_select_handled else
'CLICK'
) )
self.select_tweak_event = {"type": self.select_mouse, "value": 'CLICK_DRAG'} self.select_tweak_event = {"type": self.select_mouse, "value": 'CLICK_DRAG'}
self.pie_value = 'CLICK_DRAG' if use_pie_click_drag else 'PRESS' self.pie_value = 'CLICK_DRAG' if use_pie_click_drag else 'PRESS'
@ -1829,7 +1840,8 @@ def km_graph_editor(params):
("graph.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None), ("graph.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
("graph.paste", {"type": 'V', "value": 'PRESS', "shift": True, "ctrl": True}, ("graph.paste", {"type": 'V', "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("flipped", True)]}), {"properties": [("flipped", True)]}),
op_menu("GRAPH_MT_slider", {"type": 'D', "value": 'PRESS'}), op_menu("GRAPH_MT_key_smoothing", {"type": 'S', "value": 'PRESS', "alt": True}),
op_menu("GRAPH_MT_key_blending", {"type": 'D', "value": 'PRESS', "alt": True}),
("graph.previewrange_set", {"type": 'P', "value": 'PRESS', "ctrl": True, "alt": True}, None), ("graph.previewrange_set", {"type": 'P', "value": 'PRESS', "ctrl": True, "alt": True}, None),
("graph.view_all", {"type": 'HOME', "value": 'PRESS'}, None), ("graph.view_all", {"type": 'HOME', "value": 'PRESS'}, None),
("graph.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None), ("graph.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
@ -3576,7 +3588,7 @@ def km_grease_pencil(params):
return keymap return keymap
def _grease_pencil_selection(params, use_select_mouse=True): def _grease_pencil_selection(params, *, use_select_mouse=True):
return [ return [
# Select all # Select all
*_template_items_select_actions(params, "gpencil.select_all"), *_template_items_select_actions(params, "gpencil.select_all"),
@ -3970,7 +3982,7 @@ def km_grease_pencil_stroke_sculpt_mode(params):
items.extend([ items.extend([
# Selection # Selection
*_grease_pencil_selection(params, use_select_mouse=(params.use_fallback_tool_select_mouse == False)), *_grease_pencil_selection(params, use_select_mouse=(not params.use_fallback_tool_select_mouse)),
# Brush strength # Brush strength
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True}, ("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
@ -4321,7 +4333,7 @@ def km_grease_pencil_stroke_vertex_mode(params):
items.extend([ items.extend([
# Selection # Selection
*_grease_pencil_selection(params, use_select_mouse=(params.use_fallback_tool_select_mouse == False)), *_grease_pencil_selection(params, use_select_mouse=(not params.use_fallback_tool_select_mouse)),
# Brush strength # Brush strength
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True}, ("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
{"properties": [ {"properties": [
@ -4588,7 +4600,6 @@ def km_pose(params):
("pose.breakdown", {"type": 'E', "value": 'PRESS', "shift": True}, None), ("pose.breakdown", {"type": 'E', "value": 'PRESS', "shift": True}, None),
("pose.blend_to_neighbor", {"type": 'E', "value": 'PRESS', "shift": True, "alt": True}, None), ("pose.blend_to_neighbor", {"type": 'E', "value": 'PRESS', "shift": True, "alt": True}, None),
op_menu("VIEW3D_MT_pose_propagate", {"type": 'P', "value": 'PRESS', "alt": True}), op_menu("VIEW3D_MT_pose_propagate", {"type": 'P', "value": 'PRESS', "alt": True}),
*_template_object_hide_collection_from_number_keys(),
*_template_items_context_menu("VIEW3D_MT_pose_context_menu", params.context_menu_event), *_template_items_context_menu("VIEW3D_MT_pose_context_menu", params.context_menu_event),
]) ])
@ -6665,7 +6676,7 @@ def km_image_editor_tool_uv_select(params, *, fallback):
{"items": [ {"items": [
*([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select( *([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select(
params, "uv.select", "uv.cursor_set", fallback=fallback)), params, "uv.select", "uv.cursor_set", fallback=fallback)),
*([] if (not (params.use_fallback_tool and params.select_mouse == 'RIGHTMOUSE')) else *([] if params.use_fallback_tool_select_handled else
_template_uv_select( _template_uv_select(
type=params.select_mouse, type=params.select_mouse,
value=params.select_mouse_value, value=params.select_mouse_value,
@ -6896,7 +6907,7 @@ def km_3d_view_tool_select(params, *, fallback):
{"items": [ {"items": [
*([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select( *([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select(
params, "view3d.select", "view3d.cursor3d", operator_props=operator_props, fallback=fallback)), params, "view3d.select", "view3d.cursor3d", operator_props=operator_props, fallback=fallback)),
*([] if (not (params.use_fallback_tool and params.select_mouse == 'RIGHTMOUSE')) else *([] if params.use_fallback_tool_select_handled else
_template_view3d_select( _template_view3d_select(
type=params.select_mouse, type=params.select_mouse,
value=params.select_mouse_value, value=params.select_mouse_value,
@ -7841,7 +7852,7 @@ def km_3d_view_tool_edit_gpencil_select(params, *, fallback):
{"items": [ {"items": [
*([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select( *([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select(
params, "gpencil.select", "view3d.cursor3d", fallback=fallback)), params, "gpencil.select", "view3d.cursor3d", fallback=fallback)),
*([] if (not (params.use_fallback_tool and params.select_mouse == 'RIGHTMOUSE')) else *([] if params.use_fallback_tool_select_handled else
_template_view3d_gpencil_select( _template_view3d_gpencil_select(
type=params.select_mouse, type=params.select_mouse,
value=params.select_mouse_value, value=params.select_mouse_value,
@ -8024,7 +8035,7 @@ def km_sequencer_editor_tool_generic_select(params, *, fallback):
*([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select( *([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select(
params, "sequencer.select", "sequencer.cursor_set", cursor_prioritize=True, fallback=fallback)), params, "sequencer.select", "sequencer.cursor_set", cursor_prioritize=True, fallback=fallback)),
*([] if (not (params.use_fallback_tool and params.select_mouse == 'RIGHTMOUSE')) else *([] if params.use_fallback_tool_select_handled else
_template_sequencer_preview_select( _template_sequencer_preview_select(
type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy)), type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy)),
# Ignored for preview. # Ignored for preview.

View File

@ -372,19 +372,6 @@ class GRAPH_MT_key_snap(Menu):
layout.operator("graph.snap_cursor_value", text="Cursor Value to Selection") layout.operator("graph.snap_cursor_value", text="Cursor Value to Selection")
class GRAPH_MT_slider(Menu):
bl_label = "Slider Operators"
def draw(self, _context):
layout = self.layout
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("graph.breakdown", text="Breakdown")
layout.operator("graph.blend_to_neighbor", text="Blend to Neighbor")
layout.operator("graph.blend_to_default", text="Blend to Default Value")
layout.operator("graph.ease", text="Ease")
layout.operator("graph.gaussian_smooth", text="Smooth")
class GRAPH_MT_view_pie(Menu): class GRAPH_MT_view_pie(Menu):
bl_label = "View" bl_label = "View"
@ -526,7 +513,6 @@ classes = (
GRAPH_MT_key_snap, GRAPH_MT_key_snap,
GRAPH_MT_key_smoothing, GRAPH_MT_key_smoothing,
GRAPH_MT_key_blending, GRAPH_MT_key_blending,
GRAPH_MT_slider,
GRAPH_MT_delete, GRAPH_MT_delete,
GRAPH_MT_context_menu, GRAPH_MT_context_menu,
GRAPH_MT_channel_context_menu, GRAPH_MT_channel_context_menu,

View File

@ -3046,10 +3046,6 @@ class VIEW3D_MT_make_links(Menu):
layout.operator("object.data_transfer") layout.operator("object.data_transfer")
layout.operator("object.datalayout_transfer") layout.operator("object.datalayout_transfer")
layout.separator()
layout.operator_menu_enum("object.light_linking_receivers_link", "link_state")
layout.operator_menu_enum("object.light_linking_blockers_link", "link_state")
class VIEW3D_MT_brush_paint_modes(Menu): class VIEW3D_MT_brush_paint_modes(Menu):
bl_label = "Enabled Modes" bl_label = "Enabled Modes"

View File

@ -23,6 +23,7 @@
#include "BLI_fileops.h" #include "BLI_fileops.h"
#include "BLI_math.h" #include "BLI_math.h"
#include "BLI_path_util.h"
#include "BLI_string.h" #include "BLI_string.h"
#include "BLI_threads.h" #include "BLI_threads.h"
@ -113,7 +114,7 @@ static int blf_search_by_filepath(const char *filepath)
{ {
for (int i = 0; i < BLF_MAX_FONT; i++) { for (int i = 0; i < BLF_MAX_FONT; i++) {
const FontBLF *font = global_font[i]; const FontBLF *font = global_font[i];
if (font && STREQ(font->filepath, filepath)) { if (font && (BLI_path_cmp(font->filepath, filepath) == 0)) {
return i; return i;
} }
} }
@ -249,7 +250,7 @@ void BLF_unload(const char *filepath)
continue; continue;
} }
if (STREQ(font->filepath, filepath)) { if (BLI_path_cmp(font->filepath, filepath) == 0) {
BLI_assert(font->reference_count > 0); BLI_assert(font->reference_count > 0);
font->reference_count--; font->reference_count--;

View File

@ -1436,7 +1436,9 @@ bool blf_ensure_face(FontBLF *font)
* from our font in 3.1. In 3.4 we disable kerning here in the new version to keep spacing the * from our font in 3.1. In 3.4 we disable kerning here in the new version to keep spacing the
* same * same
* (#101506). Enable again later with change of font, placement, or rendering - Harley. */ * (#101506). Enable again later with change of font, placement, or rendering - Harley. */
if (font && font->filepath && BLI_str_endswith(font->filepath, BLF_DEFAULT_PROPORTIONAL_FONT)) { if (font && font->filepath &&
(BLI_path_cmp(BLI_path_basename(font->filepath), BLF_DEFAULT_PROPORTIONAL_FONT) == 0))
{
font->face_flags &= ~FT_FACE_FLAG_KERNING; font->face_flags &= ~FT_FACE_FLAG_KERNING;
} }
@ -1547,7 +1549,7 @@ static FontBLF *blf_font_new_impl(const char *filepath,
if (font->filepath) { if (font->filepath) {
const char *filename = BLI_path_basename(font->filepath); const char *filename = BLI_path_basename(font->filepath);
for (int i = 0; i < (int)ARRAY_SIZE(static_face_details); i++) { for (int i = 0; i < (int)ARRAY_SIZE(static_face_details); i++) {
if (STREQ(static_face_details[i].filename, filename)) { if (BLI_path_cmp(static_face_details[i].filename, filename) == 0) {
const struct FaceDetails *static_details = &static_face_details[i]; const struct FaceDetails *static_details = &static_face_details[i];
font->unicode_ranges[0] = static_details->coverage1; font->unicode_ranges[0] = static_details->coverage1;
font->unicode_ranges[1] = static_details->coverage2; font->unicode_ranges[1] = static_details->coverage2;

View File

@ -28,6 +28,9 @@ typedef enum LightLinkingType {
LIGHT_LINKING_BLOCKER, LIGHT_LINKING_BLOCKER,
} LightLinkingType; } LightLinkingType;
/* Free object's light_linking if it is not needed to hold any of collections. */
void BKE_light_linking_free_if_empty(struct Object *object);
/* Get a collection of the given light linking type of the given object. */ /* Get a collection of the given light linking type of the given object. */
struct Collection *BKE_light_linking_collection_get(const struct Object *object, struct Collection *BKE_light_linking_collection_get(const struct Object *object,
LightLinkingType link_type); LightLinkingType link_type);

View File

@ -2495,7 +2495,7 @@ static void lib_override_resync_tagging_finalize_recurse(Main *bmain,
} }
else if (!is_in_partial_resync_hierarchy) { else if (!is_in_partial_resync_hierarchy) {
/* This ID is not tagged for resync, and is part of a loop where none of the other IDs are /* This ID is not tagged for resync, and is part of a loop where none of the other IDs are
* tagged for resync, nothing else to to. */ * tagged for resync, nothing else to do. */
return; return;
} }
/* This ID is not yet tagged for resync, but is part of a loop which is (partially) tagged /* This ID is not yet tagged for resync, but is part of a loop which is (partially) tagged

View File

@ -25,6 +25,15 @@
#include "DEG_depsgraph.h" #include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h" #include "DEG_depsgraph_build.h"
void BKE_light_linking_free_if_empty(Object *object)
{
if (object->light_linking->receiver_collection == nullptr &&
object->light_linking->blocker_collection == nullptr)
{
MEM_SAFE_FREE(object->light_linking);
}
}
Collection *BKE_light_linking_collection_get(const Object *object, Collection *BKE_light_linking_collection_get(const Object *object,
const LightLinkingType link_type) const LightLinkingType link_type)
{ {
@ -108,12 +117,7 @@ void BKE_light_linking_collection_assign_only(struct Object *object,
id_us_plus(&new_collection->id); id_us_plus(&new_collection->id);
} }
/* Free if empty. */ BKE_light_linking_free_if_empty(object);
if (object->light_linking->receiver_collection == nullptr &&
object->light_linking->blocker_collection == nullptr)
{
MEM_SAFE_FREE(object->light_linking);
}
} }
} }
@ -182,8 +186,11 @@ void BKE_light_linking_add_receiver_to_collection(Main *bmain,
CollectionLightLinking *collection_light_linking = nullptr; CollectionLightLinking *collection_light_linking = nullptr;
if (id_type == ID_OB) { if (id_type == ID_OB) {
collection_light_linking = light_linking_collection_add_object( Object *object = reinterpret_cast<Object *>(receiver);
bmain, collection, reinterpret_cast<Object *>(receiver)); if (!OB_TYPE_IS_GEOMETRY(object->type)) {
return;
}
collection_light_linking = light_linking_collection_add_object(bmain, collection, object);
} }
else if (id_type == ID_GR) { else if (id_type == ID_GR) {
collection_light_linking = light_linking_collection_add_collection( collection_light_linking = light_linking_collection_add_collection(
@ -240,6 +247,10 @@ void BKE_light_linking_link_receiver_to_emitter(Main *bmain,
const LightLinkingType link_type, const LightLinkingType link_type,
const eCollectionLightLinkingState link_state) const eCollectionLightLinkingState link_state)
{ {
if (!OB_TYPE_IS_GEOMETRY(receiver->type)) {
return;
}
Collection *collection = BKE_light_linking_collection_get(emitter, link_type); Collection *collection = BKE_light_linking_collection_get(emitter, link_type);
if (!collection) { if (!collection) {

View File

@ -1444,6 +1444,16 @@ static void sculptsession_free_pbvh(Object *object)
ss->pbvh = nullptr; ss->pbvh = nullptr;
} }
ss->vert_to_poly_offsets = {};
ss->vert_to_poly_indices = {};
ss->pmap = {};
ss->edge_to_poly_offsets = {};
ss->edge_to_poly_indices = {};
ss->epmap = {};
ss->vert_to_edge_offsets = {};
ss->vert_to_edge_indices = {};
ss->vemap = {};
MEM_SAFE_FREE(ss->preview_vert_list); MEM_SAFE_FREE(ss->preview_vert_list);
ss->preview_vert_count = 0; ss->preview_vert_count = 0;

View File

@ -1418,7 +1418,7 @@ static void pbvh_faces_update_normals(PBVH *pbvh, Span<PBVHNode *> nodes)
}); });
}, },
[&]() { [&]() {
/* Update all normals connected to affected faces faces, even if not explicitly tagged. */ /* Update all normals connected to affected faces, even if not explicitly tagged. */
verts_to_update.reserve(polys_to_update.size()); verts_to_update.reserve(polys_to_update.size());
for (const int poly : polys_to_update) { for (const int poly : polys_to_update) {
verts_to_update.add_multiple(corner_verts.slice(polys[poly])); verts_to_update.add_multiple(corner_verts.slice(polys[poly]));

View File

@ -31,7 +31,7 @@ namespace blender::index_mask {
* - The second most-significant bit is not used for indices so that #max_segment_size itself can * - The second most-significant bit is not used for indices so that #max_segment_size itself can
* be stored in the #int16_t. * be stored in the #int16_t.
* - The maximum number of indices in a segment is 16384, which is generally enough to make the * - The maximum number of indices in a segment is 16384, which is generally enough to make the
* overhead per segment negilible when processing large index masks. * overhead per segment negligible when processing large index masks.
* - A power of two is used for #max_segment_size, because that allows for faster construction of * - A power of two is used for #max_segment_size, because that allows for faster construction of
* index masks for index ranges. * index masks for index ranges.
*/ */
@ -335,7 +335,7 @@ class IndexMask : private IndexMaskData {
*/ */
void to_bits(MutableBitSpan r_bits) const; void to_bits(MutableBitSpan r_bits) const;
/** /**
* Set the bools at indies inthe mask to true and all others to false. * Set the bools at indies in the mask to true and all others to false.
*/ */
void to_bools(MutableSpan<bool> r_bools) const; void to_bools(MutableSpan<bool> r_bools) const;
/** /**

View File

@ -33,9 +33,6 @@
* *
* Ideally this could be could be even closer to Python's enumerate(). We might get that in the * Ideally this could be could be even closer to Python's enumerate(). We might get that in the
* future with newer C++ versions. * future with newer C++ versions.
*
* One other important feature is the as_span method. This method returns a Span<int64_t>
* that contains the interval as individual numbers.
*/ */
#include <algorithm> #include <algorithm>
@ -325,22 +322,11 @@ class IndexRange {
return IndexRange(start_ + n, size_); return IndexRange(start_ + n, size_);
} }
/**
* Get read-only access to a memory buffer that contains the range as actual numbers.
*/
Span<int64_t> as_span() const;
friend std::ostream &operator<<(std::ostream &stream, IndexRange range) friend std::ostream &operator<<(std::ostream &stream, IndexRange range)
{ {
stream << "[" << range.start() << ", " << range.one_after_last() << ")"; stream << "[" << range.start() << ", " << range.one_after_last() << ")";
return stream; return stream;
} }
private:
static std::atomic<int64_t> s_current_array_size;
static std::atomic<int64_t *> s_current_array;
Span<int64_t> as_span_internal() const;
}; };
struct AlignedIndexRanges { struct AlignedIndexRanges {

View File

@ -766,16 +766,4 @@ template<typename T> class MutableSpan {
} }
}; };
/** This is defined here, because in `BLI_index_range.hh` `Span` is not yet defined. */
inline Span<int64_t> IndexRange::as_span() const
{
const int64_t min_required_size = start_ + size_;
const int64_t current_array_size = s_current_array_size.load(std::memory_order_acquire);
const int64_t *current_array = s_current_array.load(std::memory_order_acquire);
if (min_required_size <= current_array_size) {
return Span<int64_t>(current_array + start_, size_);
}
return this->as_span_internal();
}
} /* namespace blender */ } /* namespace blender */

View File

@ -10,40 +10,6 @@
namespace blender { namespace blender {
static RawVector<RawArray<int64_t, 0>> arrays;
static std::mutex current_array_mutex;
std::atomic<int64_t> IndexRange::s_current_array_size = 0;
std::atomic<int64_t *> IndexRange::s_current_array = nullptr;
Span<int64_t> IndexRange::as_span_internal() const
{
int64_t min_required_size = start_ + size_;
std::lock_guard<std::mutex> lock(current_array_mutex);
/* Double checked lock. */
if (min_required_size <= s_current_array_size) {
return Span<int64_t>(s_current_array + start_, size_);
}
/* Isolate, because a mutex is locked. */
threading::isolate_task([&]() {
int64_t new_size = std::max<int64_t>(1000, power_of_2_max_u(min_required_size));
RawArray<int64_t, 0> new_array(new_size);
threading::parallel_for(IndexRange(new_size), 4096, [&](const IndexRange range) {
for (const int64_t i : range) {
new_array[i] = i;
}
});
arrays.append(std::move(new_array));
s_current_array.store(arrays.last().data(), std::memory_order_release);
s_current_array_size.store(new_size, std::memory_order_release);
});
return Span<int64_t>(s_current_array + start_, size_);
}
AlignedIndexRanges split_index_range_by_alignment(const IndexRange range, const int64_t alignment) AlignedIndexRanges split_index_range_by_alignment(const IndexRange range, const int64_t alignment)
{ {
BLI_assert(is_power_of_2_i(alignment)); BLI_assert(is_power_of_2_i(alignment));

View File

@ -5,7 +5,8 @@
namespace blender::offset_indices { namespace blender::offset_indices {
OffsetIndices<int> accumulate_counts_to_offsets(MutableSpan<int> counts_to_offsets, const int start_offset) OffsetIndices<int> accumulate_counts_to_offsets(MutableSpan<int> counts_to_offsets,
const int start_offset)
{ {
int offset = start_offset; int offset = start_offset;
for (const int i : counts_to_offsets.index_range().drop_back(1)) { for (const int i : counts_to_offsets.index_range().drop_back(1)) {

View File

@ -655,7 +655,7 @@ void BLI_path_normalize_unc_16(wchar_t *path_16)
void BLI_path_rel(char path[FILE_MAX], const char *basepath) void BLI_path_rel(char path[FILE_MAX], const char *basepath)
{ {
BLI_string_debug_size_after_nil(path, FILE_MAX); BLI_string_debug_size_after_nil(path, FILE_MAX);
/* A `basepath` starting with `//` will be be made relative multiple times. */ /* A `basepath` starting with `//` will be made relative multiple times. */
BLI_assert_msg(!BLI_path_is_rel(basepath), "The 'basepath' cannot start with '//'!"); BLI_assert_msg(!BLI_path_is_rel(basepath), "The 'basepath' cannot start with '//'!");
const char *lslash; const char *lslash;
@ -1095,7 +1095,7 @@ void BLI_path_to_display_name(char *display_name, int display_name_maxncpy, cons
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) bool BLI_path_abs(char path[FILE_MAX], const char *basepath)
{ {
BLI_string_debug_size_after_nil(path, FILE_MAX); BLI_string_debug_size_after_nil(path, FILE_MAX);
/* A `basepath` starting with `//` will be be made absolute multiple times. */ /* A `basepath` starting with `//` will be made absolute multiple times. */
BLI_assert_msg(!BLI_path_is_rel(basepath), "The 'basepath' cannot start with '//'!"); BLI_assert_msg(!BLI_path_is_rel(basepath), "The 'basepath' cannot start with '//'!");
const bool wasrelative = BLI_path_is_rel(path); const bool wasrelative = BLI_path_is_rel(path);

View File

@ -44,7 +44,8 @@ int BLI_windows_get_executable_dir(char *str)
return 1; return 1;
} }
bool BLI_windows_is_store_install(void) { bool BLI_windows_is_store_install(void)
{
char install_dir[FILE_MAXDIR]; char install_dir[FILE_MAXDIR];
BLI_windows_get_executable_dir(install_dir); BLI_windows_get_executable_dir(install_dir);
return (BLI_strcasestr(install_dir, "\\WindowsApps\\") != NULL); return (BLI_strcasestr(install_dir, "\\WindowsApps\\") != NULL);

View File

@ -219,17 +219,6 @@ TEST(index_range, TakeBackLargeN)
EXPECT_EQ(slice.size(), 4); EXPECT_EQ(slice.size(), 4);
} }
TEST(index_range, AsSpan)
{
IndexRange range = IndexRange(4, 6);
Span<int64_t> span = range.as_span();
EXPECT_EQ(span.size(), 6);
EXPECT_EQ(span[0], 4);
EXPECT_EQ(span[1], 5);
EXPECT_EQ(span[2], 6);
EXPECT_EQ(span[3], 7);
}
TEST(index_range, constexpr_) TEST(index_range, constexpr_)
{ {
constexpr IndexRange range = IndexRange(1, 1); constexpr IndexRange range = IndexRange(1, 1);

View File

@ -90,7 +90,7 @@ TEST(string, StrCopyUTF8_TruncateEncoding)
TEST(string, StrCopyUTF8_TerminateEncodingEarly) TEST(string, StrCopyUTF8_TerminateEncodingEarly)
{ {
/* A UTF8 sequence that has a null byte before the sequence ends. /* A UTF8 sequence that has a null byte before the sequence ends.
* Ensure the the UTF8 sequence does not step over the null byte. */ * Ensure the UTF8 sequence does not step over the null byte. */
#define STRNCPY_UTF8_TERMINATE_EARLY(byte_size, ...) \ #define STRNCPY_UTF8_TERMINATE_EARLY(byte_size, ...) \
{ \ { \
char src[] = {__VA_ARGS__, 0}; \ char src[] = {__VA_ARGS__, 0}; \

View File

@ -3986,7 +3986,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
/* In case the current scene is a liboverride, while the ID pointer itself remains valid, /* In case the current scene is a liboverride, while the ID pointer itself remains valid,
* above update of liboverrides will have completely invalidated its old content, so the * above update of liboverrides will have completely invalidated its old content, so the
* current viewlayer needs to be searched for again. */ * current view-layer needs to be searched for again. */
if (bfd->cur_view_layer != nullptr) { if (bfd->cur_view_layer != nullptr) {
bfd->cur_view_layer = BKE_view_layer_find(bfd->curscene, cur_view_layer_name.c_str()); bfd->cur_view_layer = BKE_view_layer_find(bfd->curscene, cur_view_layer_name.c_str());
} }

View File

@ -483,11 +483,18 @@ void Cache::eval_runtime_data(Object &object_eval) const
runtime.shadow_set_membership = EmitterSetMembership::SET_MEMBERSHIP_ALL; runtime.shadow_set_membership = EmitterSetMembership::SET_MEMBERSHIP_ALL;
} }
const bool need_runtime = (memcmp(&runtime, &runtime_no_links, sizeof(runtime)) != 0);
/* Assign, allocating light linking on demand if needed. */ /* Assign, allocating light linking on demand if needed. */
if (object_eval.light_linking) { if (object_eval.light_linking) {
object_eval.light_linking->runtime = runtime; object_eval.light_linking->runtime = runtime;
if (!need_runtime) {
/* Note that this will only remove lazily allocated light_linking on the evaluated object,
* as an empty light_linking is not allowed on the original object. */
BKE_light_linking_free_if_empty(&object_eval);
}
} }
else if (memcmp(&runtime, &runtime_no_links, sizeof(runtime)) != 0) { else if (need_runtime) {
object_eval.light_linking = MEM_cnew<LightLinking>(__func__); object_eval.light_linking = MEM_cnew<LightLinking>(__func__);
object_eval.light_linking->runtime = runtime; object_eval.light_linking->runtime = runtime;
} }

View File

@ -73,7 +73,7 @@ class EmitterData {
static constexpr int MAX_COLLECTION_ID = 63; static constexpr int MAX_COLLECTION_ID = 63;
/* Mask of a light linking collection this emitter uses in its configuration. /* Mask of a light linking collection this emitter uses in its configuration.
* A single bit is set in this bitfield which corresponds to an identifier of a light linking * A single bit is set in this bit-field which corresponds to an identifier of a light linking
* collection in the scene. */ * collection in the scene. */
uint64_t collection_mask = 0; uint64_t collection_mask = 0;
@ -121,7 +121,7 @@ class EmitterDataMap {
} }
private: private:
/* Get linked collection depending on whether this is emitter information os for light or shadow /* Get linked collection depending on whether this is emitter information for light or shadow
* linking. */ * linking. */
/* TODO(sergey): Check whether template specialization is preferred here. */ /* TODO(sergey): Check whether template specialization is preferred here. */
inline const Collection *get_collection(const Object &emitter) const inline const Collection *get_collection(const Object &emitter) const

View File

@ -32,9 +32,6 @@ void ObjectRuntimeBackup::init_from_object(Object *object)
if (object->light_linking) { if (object->light_linking) {
light_linking_runtime = object->light_linking->runtime; light_linking_runtime = object->light_linking->runtime;
} }
else {
memset(&light_linking_runtime, 0, sizeof(light_linking_runtime));
}
BKE_object_runtime_reset(object); BKE_object_runtime_reset(object);
/* Keep bbox (for now at least). */ /* Keep bbox (for now at least). */
object->runtime.bb = runtime.bb; object->runtime.bb = runtime.bb;
@ -128,8 +125,13 @@ void ObjectRuntimeBackup::restore_to_object(Object *object)
} }
} }
if (object->light_linking) { if (light_linking_runtime) {
object->light_linking->runtime = light_linking_runtime; /* Lazily allocate light linking on the evaluated object for the cases when the object is only
* a receiver or a blocker and does not need its own LightLinking on the original object. */
if (!object->light_linking) {
object->light_linking = MEM_cnew<LightLinking>(__func__);
}
object->light_linking->runtime = *light_linking_runtime;
} }
object->base_flag = base_flag; object->base_flag = base_flag;

View File

@ -12,6 +12,7 @@
#include "BLI_session_uuid.h" #include "BLI_session_uuid.h"
#include "intern/depsgraph_type.h"
#include "intern/eval/deg_eval_runtime_backup_modifier.h" #include "intern/eval/deg_eval_runtime_backup_modifier.h"
#include "intern/eval/deg_eval_runtime_backup_pose.h" #include "intern/eval/deg_eval_runtime_backup_pose.h"
@ -39,7 +40,7 @@ class ObjectRuntimeBackup {
void restore_pose_channel_runtime_data(Object *object); void restore_pose_channel_runtime_data(Object *object);
Object_Runtime runtime; Object_Runtime runtime;
LightLinkingRuntime light_linking_runtime; optional<LightLinkingRuntime> light_linking_runtime;
short base_flag; short base_flag;
unsigned short base_local_view_bits; unsigned short base_local_view_bits;
Map<SessionUUID, ModifierDataBackup> modifier_runtime_data; Map<SessionUUID, ModifierDataBackup> modifier_runtime_data;

View File

@ -1213,7 +1213,7 @@ void EEVEE_material_transparent_output_init(EEVEE_Data *vedata)
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->transparent_accum)}); {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->transparent_accum)});
{ {
/* This pass Accumulate 1 sample of the transparent pass into the the transparent /* This pass Accumulate 1 sample of the transparent pass into the transparent
* accumulation buffer. */ * accumulation buffer. */
DRW_PASS_CREATE(psl->transparent_accum_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL); DRW_PASS_CREATE(psl->transparent_accum_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL);
DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_renderpasses_accumulate_sh_get(), DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_renderpasses_accumulate_sh_get(),

View File

@ -300,7 +300,7 @@ GPUShader *EEVEE_shaders_probe_filter_visibility_sh_get(void)
{ {
if (e_data.probe_filter_visibility_sh == nullptr) { if (e_data.probe_filter_visibility_sh == nullptr) {
e_data.probe_filter_visibility_sh = DRW_shader_create_from_info_name( e_data.probe_filter_visibility_sh = DRW_shader_create_from_info_name(
"eevee_legacy_probe_filter_visiblity"); "eevee_legacy_probe_filter_visibility");
} }
return e_data.probe_filter_visibility_sh; return e_data.probe_filter_visibility_sh;
} }

View File

@ -121,7 +121,7 @@ GPU_SHADER_CREATE_INFO(eevee_legacy_probe_filter_diffuse_hl2)
.auto_resource_location(true); .auto_resource_location(true);
/* EEVEE_shaders_probe_filter_visibility_sh_get */ /* EEVEE_shaders_probe_filter_visibility_sh_get */
GPU_SHADER_CREATE_INFO(eevee_legacy_probe_filter_visiblity) GPU_SHADER_CREATE_INFO(eevee_legacy_probe_filter_visibility)
.define("IRRADIANCE_HL2") .define("IRRADIANCE_HL2")
.additional_info("eevee_legacy_irradiance_lib") .additional_info("eevee_legacy_irradiance_lib")
.additional_info("draw_fullscreen") .additional_info("draw_fullscreen")

View File

@ -203,7 +203,7 @@ MaterialPass MaterialModule::material_pass_get(Object *ob,
matpass.sub_pass = nullptr; matpass.sub_pass = nullptr;
} }
else { else {
ShaderKey shader_key(matpass.gpumat, geometry_type, pipeline_type); ShaderKey shader_key(matpass.gpumat, geometry_type, pipeline_type, blender_mat->blend_flag);
PassMain::Sub *shader_sub = shader_map_.lookup_or_add_cb(shader_key, [&]() { PassMain::Sub *shader_sub = shader_map_.lookup_or_add_cb(shader_key, [&]() {
/* First time encountering this shader. Create a sub that will contain materials using it. */ /* First time encountering this shader. Create a sub that will contain materials using it. */

View File

@ -108,7 +108,7 @@ static inline eMaterialGeometry to_material_geometry(const Object *ob)
/** Unique key to identify each material in the hash-map. */ /** Unique key to identify each material in the hash-map. */
struct MaterialKey { struct MaterialKey {
Material *mat; ::Material *mat;
uint64_t options; uint64_t options;
MaterialKey(::Material *mat_, eMaterialGeometry geometry, eMaterialPipeline surface_pipeline) MaterialKey(::Material *mat_, eMaterialGeometry geometry, eMaterialPipeline surface_pipeline)
@ -145,10 +145,14 @@ struct ShaderKey {
GPUShader *shader; GPUShader *shader;
uint64_t options; uint64_t options;
ShaderKey(GPUMaterial *gpumat, eMaterialGeometry geometry, eMaterialPipeline pipeline) ShaderKey(GPUMaterial *gpumat,
eMaterialGeometry geometry,
eMaterialPipeline pipeline,
char blend_flags)
{ {
shader = GPU_material_get_shader(gpumat); shader = GPU_material_get_shader(gpumat);
options = shader_uuid_from_material_type(pipeline, geometry); options = blend_flags;
options = (options << 6u) | shader_uuid_from_material_type(pipeline, geometry);
options = (options << 16u) | shader_closure_bits_from_flag(gpumat); options = (options << 16u) | shader_closure_bits_from_flag(gpumat);
} }

View File

@ -12,13 +12,9 @@ namespace blender::draw::overlay {
class Background { class Background {
private: private:
const SelectionType selection_type_;
PassSimple bg_ps_ = {"Background"}; PassSimple bg_ps_ = {"Background"};
public: public:
Background(const SelectionType selection_type) : selection_type_(selection_type){};
void begin_sync(Resources &res, const State &state) void begin_sync(Resources &res, const State &state)
{ {
DRWState pass_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_BACKGROUND; DRWState pass_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_BACKGROUND;

View File

@ -17,8 +17,6 @@ namespace blender::draw::overlay {
class Grid { class Grid {
private: private:
const SelectionType selection_type_;
UniformBuffer<OVERLAY_GridData> data_; UniformBuffer<OVERLAY_GridData> data_;
PassSimple grid_ps_ = {"grid_ps_"}; PassSimple grid_ps_ = {"grid_ps_"};
@ -32,8 +30,6 @@ class Grid {
bool enabled_ = false; bool enabled_ = false;
public: public:
Grid(const SelectionType selection_type) : selection_type_(selection_type){};
void begin_sync(Resources &res, const State &state, const View &view) void begin_sync(Resources &res, const State &state, const View &view)
{ {
this->update_ubo(state, view); this->update_ubo(state, view);

View File

@ -33,11 +33,11 @@ class Instance {
State state; State state;
/** Overlay types. */ /** Overlay types. */
Background background = {selection_type_}; Background background;
Prepass prepass = {selection_type_}; Prepass prepass;
Metaballs metaballs = {selection_type_}; Metaballs metaballs = {selection_type_};
Empties empties = {selection_type_}; Empties empties = {selection_type_};
Grid grid = {selection_type_}; Grid grid;
Instance(const SelectionType selection_type) : selection_type_(selection_type){}; Instance(const SelectionType selection_type) : selection_type_(selection_type){};

View File

@ -15,14 +15,10 @@ namespace blender::draw::overlay {
class Prepass { class Prepass {
private: private:
const SelectionType selection_type_;
PassMain prepass_ps_ = {"prepass"}; PassMain prepass_ps_ = {"prepass"};
PassMain prepass_in_front_ps_ = {"prepass_in_front"}; PassMain prepass_in_front_ps_ = {"prepass_in_front"};
public: public:
Prepass(const SelectionType selection_type) : selection_type_(selection_type){};
void begin_sync(Resources &res, const State &state) void begin_sync(Resources &res, const State &state)
{ {
auto init_pass = [&](PassMain &pass) { auto init_pass = [&](PassMain &pass) {

View File

@ -15,8 +15,9 @@ ShaderModule::ShaderPtr ShaderModule::selectable_shader(const char *create_info_
/* TODO: This is what it should be like with all variations defined with create infos. */ /* TODO: This is what it should be like with all variations defined with create infos. */
// std::string create_info_name = base_create_info; // std::string create_info_name = base_create_info;
// create_info_name += SelectEngineT::shader_suffix; // create_info_name += SelectEngineT::shader_suffix;
// create_info_name += ClippingEnabled ? "_clipped" : ""; // create_info_name += clipping_enabled_ ? "_clipped" : "";
// this->shader_ = GPU_shader_create_from_info_name(create_info_name.c_str()); // this->shader_ = GPU_shader_create_from_info_name(create_info_name.c_str());
UNUSED_VARS(clipping_enabled_);
/* WORKAROUND: ... but for now, we have to patch the create info used by the old engine. */ /* WORKAROUND: ... but for now, we have to patch the create info used by the old engine. */
gpu::shader::ShaderCreateInfo info = *reinterpret_cast<const gpu::shader::ShaderCreateInfo *>( gpu::shader::ShaderCreateInfo info = *reinterpret_cast<const gpu::shader::ShaderCreateInfo *>(

View File

@ -1,4 +1,3 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */ /* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file /** \file

View File

@ -122,10 +122,11 @@ void DofPass::init(const SceneState &scene_state)
int2 half_res = scene_state.resolution / 2; int2 half_res = scene_state.resolution / 2;
half_res = {max_ii(half_res.x, 1), max_ii(half_res.y, 1)}; half_res = {max_ii(half_res.x, 1), max_ii(half_res.y, 1)};
source_tx_.ensure_2d(GPU_RGBA16F, half_res, GPU_TEXTURE_USAGE_SHADER_READ, nullptr, 3); eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_MIP_SWIZZLE_VIEW;
source_tx_.ensure_2d(GPU_RGBA16F, half_res, usage, nullptr, 3);
source_tx_.ensure_mip_views(); source_tx_.ensure_mip_views();
source_tx_.filter_mode(true); source_tx_.filter_mode(true);
coc_halfres_tx_.ensure_2d(GPU_RG8, half_res, GPU_TEXTURE_USAGE_SHADER_READ, nullptr, 3); coc_halfres_tx_.ensure_2d(GPU_RG8, half_res, usage, nullptr, 3);
coc_halfres_tx_.ensure_mip_views(); coc_halfres_tx_.ensure_mip_views();
coc_halfres_tx_.filter_mode(true); coc_halfres_tx_.filter_mode(true);

View File

@ -410,40 +410,41 @@ static void gpencil_primitive_status_indicators(bContext *C, tGPDprimitive *tgpi
const int cur_subdiv = tgpi->type == GP_STROKE_BOX ? tgpi->tot_edges - 1 : tgpi->tot_edges - 2; const int cur_subdiv = tgpi->type == GP_STROKE_BOX ? tgpi->tot_edges - 1 : tgpi->tot_edges - 2;
if (tgpi->type == GP_STROKE_LINE) { if (tgpi->type == GP_STROKE_LINE) {
BLI_strncpy(msg_str, BLI_strncpy(
TIP_("Line: ESC to cancel, LMB set origin, Enter/MMB to confirm, WHEEL/+- to " msg_str,
"adjust subdivision number, Shift to align, Alt to center, E: extrude"), TIP_("Line: ESC to cancel, LMB set origin, Enter/MMB to confirm, WHEEL/+- to "
UI_MAX_DRAW_STR); "adjust subdivision number, Shift to align, Alt to center, E: extrude, G: grab"),
UI_MAX_DRAW_STR);
} }
else if (tgpi->type == GP_STROKE_POLYLINE) { else if (tgpi->type == GP_STROKE_POLYLINE) {
BLI_strncpy(msg_str, BLI_strncpy(msg_str,
TIP_("Polyline: ESC to cancel, LMB to set, Enter/MMB to confirm, WHEEL/+- to " TIP_("Polyline: ESC to cancel, LMB to set, Enter/MMB to confirm, WHEEL/+- to "
"adjust subdivision number, Shift to align"), "adjust subdivision number, Shift to align, G: grab"),
UI_MAX_DRAW_STR); UI_MAX_DRAW_STR);
} }
else if (tgpi->type == GP_STROKE_BOX) { else if (tgpi->type == GP_STROKE_BOX) {
BLI_strncpy(msg_str, BLI_strncpy(msg_str,
TIP_("Rectangle: ESC to cancel, LMB set origin, Enter/MMB to confirm, WHEEL/+- " TIP_("Rectangle: ESC to cancel, LMB set origin, Enter/MMB to confirm, WHEEL/+- "
"to adjust subdivision number, Shift to square, Alt to center"), "to adjust subdivision number, Shift to square, Alt to center, G: grab"),
UI_MAX_DRAW_STR); UI_MAX_DRAW_STR);
} }
else if (tgpi->type == GP_STROKE_CIRCLE) { else if (tgpi->type == GP_STROKE_CIRCLE) {
BLI_strncpy(msg_str, BLI_strncpy(msg_str,
TIP_("Circle: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust subdivision " TIP_("Circle: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust subdivision "
"number, Shift to square, Alt to center"), "number, Shift to square, Alt to center, G: grab"),
UI_MAX_DRAW_STR); UI_MAX_DRAW_STR);
} }
else if (tgpi->type == GP_STROKE_ARC) { else if (tgpi->type == GP_STROKE_ARC) {
BLI_strncpy( BLI_strncpy(
msg_str, msg_str,
TIP_("Arc: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust subdivision number, " TIP_("Arc: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust subdivision number, "
"Shift to square, Alt to center, M: Flip, E: extrude"), "Shift to square, Alt to center, M: Flip, E: extrude, G: grab"),
UI_MAX_DRAW_STR); UI_MAX_DRAW_STR);
} }
else if (tgpi->type == GP_STROKE_CURVE) { else if (tgpi->type == GP_STROKE_CURVE) {
BLI_strncpy(msg_str, BLI_strncpy(msg_str,
TIP_("Curve: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust subdivision " TIP_("Curve: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust subdivision "
"number, Shift to square, Alt to center, E: extrude"), "number, Shift to square, Alt to center, E: extrude, G: grab"),
UI_MAX_DRAW_STR); UI_MAX_DRAW_STR);
} }
@ -1618,7 +1619,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
copy_v2fl_v2i(tgpi->mval, event->mval); copy_v2fl_v2i(tgpi->mval, event->mval);
if (tgpi->flag == IN_MOVE) { if (tgpi->flag == IN_MOVE) {
bool is_mouse_event = true;
switch (event->type) { switch (event->type) {
case MOUSEMOVE: { case MOUSEMOVE: {
gpencil_primitive_move(tgpi, false); gpencil_primitive_move(tgpi, false);
@ -1639,8 +1640,14 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
} }
break; break;
} }
default: {
is_mouse_event = false; /* Prevent overwriting `tgpi->mvalo`. */
break;
}
}
if (is_mouse_event) {
copy_v2_v2(tgpi->mvalo, tgpi->mval);
} }
copy_v2_v2(tgpi->mvalo, tgpi->mval);
return OPERATOR_RUNNING_MODAL; return OPERATOR_RUNNING_MODAL;
} }

View File

@ -373,9 +373,7 @@ ScrArea *ED_screen_temp_space_open(struct bContext *C,
bool dialog); bool dialog);
void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg); void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
void ED_screens_footer_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg); void ED_screens_footer_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
void ED_screens_navigation_bar_tools_menu_create(struct bContext *C, void ED_screens_region_flip_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
struct uiLayout *layout,
void *arg);
/** /**
* \return true if any active area requires to see in 3D. * \return true if any active area requires to see in 3D.
*/ */

View File

@ -1245,7 +1245,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *ev
uiItemMenuF(layout, uiItemMenuF(layout,
IFACE_("Navigation Bar"), IFACE_("Navigation Bar"),
ICON_NONE, ICON_NONE,
ED_screens_navigation_bar_tools_menu_create, ED_screens_region_flip_menu_create,
nullptr); nullptr);
} }
else if (region->regiontype == RGN_TYPE_FOOTER) { else if (region->regiontype == RGN_TYPE_FOOTER) {

View File

@ -3631,6 +3631,26 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
} }
} }
/**
* Return the jump type used for cursor motion & back-space/delete actions.
*/
static eStrCursorJumpType ui_textedit_jump_type_from_event(const wmEvent *event)
{
#ifdef __APPLE__
if (event->modifier & KM_OSKEY) {
return STRCUR_JUMP_ALL;
}
if (event->modifier & KM_ALT) {
return STRCUR_JUMP_DELIM;
}
#else
if (event->modifier & KM_CTRL) {
return STRCUR_JUMP_DELIM;
}
#endif
return STRCUR_JUMP_NONE;
}
static void ui_do_but_textedit( static void ui_do_but_textedit(
bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{ {
@ -3777,17 +3797,10 @@ static void ui_do_but_textedit(
break; break;
case EVT_RIGHTARROWKEY: case EVT_RIGHTARROWKEY:
case EVT_LEFTARROWKEY: { case EVT_LEFTARROWKEY: {
eStrCursorJumpDirection direction = (event->type == EVT_RIGHTARROWKEY) ? STRCUR_DIR_NEXT : const eStrCursorJumpDirection direction = (event->type == EVT_RIGHTARROWKEY) ?
STRCUR_DIR_PREV; STRCUR_DIR_NEXT :
#ifdef __APPLE__ STRCUR_DIR_PREV;
eStrCursorJumpType jump = (event->modifier & KM_OSKEY) ? const eStrCursorJumpType jump = ui_textedit_jump_type_from_event(event);
STRCUR_JUMP_ALL :
((event->modifier & KM_ALT) ? STRCUR_JUMP_DELIM :
STRCUR_JUMP_NONE);
#else
eStrCursorJumpType jump = (event->modifier & KM_CTRL) ? STRCUR_JUMP_DELIM :
STRCUR_JUMP_NONE;
#endif
ui_textedit_move(but, data, direction, event->modifier & KM_SHIFT, jump); ui_textedit_move(but, data, direction, event->modifier & KM_SHIFT, jump);
retval = WM_UI_HANDLER_BREAK; retval = WM_UI_HANDLER_BREAK;
break; break;
@ -3833,17 +3846,9 @@ static void ui_do_but_textedit(
break; break;
case EVT_DELKEY: case EVT_DELKEY:
case EVT_BACKSPACEKEY: { case EVT_BACKSPACEKEY: {
eStrCursorJumpDirection direction = (event->type == EVT_DELKEY) ? STRCUR_DIR_NEXT : const eStrCursorJumpDirection direction = (event->type == EVT_DELKEY) ? STRCUR_DIR_NEXT :
STRCUR_DIR_PREV; STRCUR_DIR_PREV;
#ifdef __APPLE__ const eStrCursorJumpType jump = ui_textedit_jump_type_from_event(event);
eStrCursorJumpType jump = (event->modifier & KM_OSKEY) ?
STRCUR_JUMP_ALL :
((event->modifier & KM_ALT) ? STRCUR_JUMP_DELIM :
STRCUR_JUMP_NONE);
#else
eStrCursorJumpType jump = (event->modifier & KM_CTRL) ? STRCUR_JUMP_DELIM :
STRCUR_JUMP_NONE;
#endif
changed = ui_textedit_delete(but, data, direction, jump); changed = ui_textedit_delete(but, data, direction, jump);
retval = WM_UI_HANDLER_BREAK; retval = WM_UI_HANDLER_BREAK;
break; break;

View File

@ -4297,10 +4297,6 @@ static void screen_area_menu_items(ScrArea *area, uiLayout *layout)
void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg)) void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
{ {
ScrArea *area = CTX_wm_area(C); ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
const char *but_flip_str = (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) == RGN_ALIGN_TOP) ?
IFACE_("Flip to Bottom") :
IFACE_("Flip to Top");
{ {
PointerRNA ptr; PointerRNA ptr;
RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, area->spacedata.first, &ptr); RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, area->spacedata.first, &ptr);
@ -4322,12 +4318,9 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN
"SCREEN_OT_header_toggle_menus"); "SCREEN_OT_header_toggle_menus");
} }
/* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
if (!ELEM(area->spacetype, SPACE_TOPBAR)) { if (!ELEM(area->spacetype, SPACE_TOPBAR)) {
uiItemS(layout); uiItemS(layout);
uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip"); ED_screens_region_flip_menu_create(C, layout, NULL);
uiItemS(layout); uiItemS(layout);
screen_area_menu_items(area, layout); screen_area_menu_items(area, layout);
} }
@ -4336,31 +4329,26 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN
void ED_screens_footer_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg)) void ED_screens_footer_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
{ {
ScrArea *area = CTX_wm_area(C); ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
const char *but_flip_str = (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) == RGN_ALIGN_TOP) ?
IFACE_("Flip to Bottom") :
IFACE_("Flip to Top");
{ {
PointerRNA ptr; PointerRNA ptr;
RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, area->spacedata.first, &ptr); RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, area->spacedata.first, &ptr);
uiItemR(layout, &ptr, "show_region_footer", 0, IFACE_("Show Footer"), ICON_NONE); uiItemR(layout, &ptr, "show_region_footer", 0, IFACE_("Show Footer"), ICON_NONE);
} }
/* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */ ED_screens_region_flip_menu_create(C, layout, NULL);
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip");
uiItemS(layout); uiItemS(layout);
screen_area_menu_items(area, layout); screen_area_menu_items(area, layout);
} }
void ED_screens_navigation_bar_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg)) void ED_screens_region_flip_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
{ {
const ARegion *region = CTX_wm_region(C); const ARegion *region = CTX_wm_region(C);
const char *but_flip_str = (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) == RGN_ALIGN_LEFT) ? const short region_alignment = RGN_ALIGN_ENUM_FROM_MASK(region->alignment);
IFACE_("Flip to Right") : const char *but_flip_str = region_alignment == RGN_ALIGN_LEFT ? IFACE_("Flip to Right") :
IFACE_("Flip to Left"); region_alignment == RGN_ALIGN_RIGHT ? IFACE_("Flip to Left") :
region_alignment == RGN_ALIGN_BOTTOM ? IFACE_("Flip to Top") :
IFACE_("Flip to Bottom");
/* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */ /* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT); uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
@ -4411,7 +4399,7 @@ static int screen_context_menu_invoke(bContext *C,
else if (region->regiontype == RGN_TYPE_NAV_BAR) { else if (region->regiontype == RGN_TYPE_NAV_BAR) {
uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Navigation Bar"), ICON_NONE); uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Navigation Bar"), ICON_NONE);
uiLayout *layout = UI_popup_menu_layout(pup); uiLayout *layout = UI_popup_menu_layout(pup);
ED_screens_navigation_bar_tools_menu_create(C, layout, NULL); ED_screens_region_flip_menu_create(C, layout, NULL);
UI_popup_menu_end(C, pup); UI_popup_menu_end(C, pup);
} }
} }

View File

@ -1180,7 +1180,7 @@ static void vertex_paint_init_session(Depsgraph *depsgraph,
BKE_sculpt_toolsettings_data_ensure(scene); BKE_sculpt_toolsettings_data_ensure(scene);
BLI_assert(ob->sculpt == nullptr); BLI_assert(ob->sculpt == nullptr);
ob->sculpt = (SculptSession *)MEM_callocN(sizeof(SculptSession), "sculpt session"); ob->sculpt = MEM_new<SculptSession>(__func__);
ob->sculpt->mode_type = object_mode; ob->sculpt->mode_type = object_mode;
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, true); BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, true);

View File

@ -169,7 +169,7 @@ static void SCULPT_dynamic_topology_disable_ex(
CustomData_free_layer_named(&me->pdata, ".sculpt_face_set", me->totpoly); CustomData_free_layer_named(&me->pdata, ".sculpt_face_set", me->totpoly);
me->face_sets_color_default = 1; me->face_sets_color_default = 1;
/* Sync the visibility to vertices manually as the pmap is still not initialized. */ /* Sync the visibility to vertices manually as the `pmap` is still not initialized. */
bool *hide_vert = (bool *)CustomData_get_layer_named_for_write( bool *hide_vert = (bool *)CustomData_get_layer_named_for_write(
&me->vdata, CD_PROP_BOOL, ".hide_vert", me->totvert); &me->vdata, CD_PROP_BOOL, ".hide_vert", me->totvert);
if (hide_vert != nullptr) { if (hide_vert != nullptr) {

View File

@ -3405,9 +3405,6 @@ static void draw_background_color(const SpaceNode &snode)
void node_draw_space(const bContext &C, ARegion &region) void node_draw_space(const bContext &C, ARegion &region)
{ {
if (G.is_rendering) {
return;
}
wmWindow *win = CTX_wm_window(&C); wmWindow *win = CTX_wm_window(&C);
SpaceNode &snode = *CTX_wm_space_node(&C); SpaceNode &snode = *CTX_wm_space_node(&C);
View2D &v2d = region.v2d; View2D &v2d = region.v2d;

View File

@ -1155,6 +1155,7 @@ void ED_spacetype_node()
art->cursor = node_cursor; art->cursor = node_cursor;
art->event_cursor = true; art->event_cursor = true;
art->clip_gizmo_events_by_ui = true; art->clip_gizmo_events_by_ui = true;
art->lock = 1;
BLI_addhead(&st->regiontypes, art); BLI_addhead(&st->regiontypes, art);

View File

@ -418,10 +418,6 @@ static void update_visible_columns(ListBase &columns, DataSource &data_source)
static void spreadsheet_main_region_draw(const bContext *C, ARegion *region) static void spreadsheet_main_region_draw(const bContext *C, ARegion *region)
{ {
if (G.is_rendering) {
return;
}
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
sspreadsheet->runtime->cache.set_all_unused(); sspreadsheet->runtime->cache.set_all_unused();
spreadsheet_update_context(C); spreadsheet_update_context(C);
@ -518,9 +514,6 @@ static void spreadsheet_header_region_init(wmWindowManager * /*wm*/, ARegion *re
static void spreadsheet_header_region_draw(const bContext *C, ARegion *region) static void spreadsheet_header_region_draw(const bContext *C, ARegion *region)
{ {
if (G.is_rendering) {
return;
}
spreadsheet_update_context(C); spreadsheet_update_context(C);
ED_region_header(C, region); ED_region_header(C, region);
} }
@ -574,9 +567,6 @@ static void spreadsheet_footer_region_init(wmWindowManager * /*wm*/, ARegion *re
static void spreadsheet_footer_region_draw(const bContext *C, ARegion *region) static void spreadsheet_footer_region_draw(const bContext *C, ARegion *region)
{ {
if (G.is_rendering) {
return;
}
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
SpaceSpreadsheet_Runtime *runtime = sspreadsheet->runtime; SpaceSpreadsheet_Runtime *runtime = sspreadsheet->runtime;
std::stringstream ss; std::stringstream ss;
@ -641,9 +631,6 @@ static void spreadsheet_dataset_region_listener(const wmRegionListenerParams *pa
static void spreadsheet_dataset_region_draw(const bContext *C, ARegion *region) static void spreadsheet_dataset_region_draw(const bContext *C, ARegion *region)
{ {
if (G.is_rendering) {
return;
}
spreadsheet_update_context(C); spreadsheet_update_context(C);
ED_region_panels(C, region); ED_region_panels(C, region);
} }
@ -736,6 +723,7 @@ void ED_spacetype_spreadsheet()
art = MEM_cnew<ARegionType>("spacetype spreadsheet region"); art = MEM_cnew<ARegionType>("spacetype spreadsheet region");
art->regionid = RGN_TYPE_WINDOW; art->regionid = RGN_TYPE_WINDOW;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
art->lock = 1;
art->init = spreadsheet_main_region_init; art->init = spreadsheet_main_region_init;
art->draw = spreadsheet_main_region_draw; art->draw = spreadsheet_main_region_draw;
@ -748,6 +736,7 @@ void ED_spacetype_spreadsheet()
art->prefsizey = HEADERY; art->prefsizey = HEADERY;
art->keymapflag = 0; art->keymapflag = 0;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
art->lock = 1;
art->init = spreadsheet_header_region_init; art->init = spreadsheet_header_region_init;
art->draw = spreadsheet_header_region_draw; art->draw = spreadsheet_header_region_draw;
@ -761,6 +750,7 @@ void ED_spacetype_spreadsheet()
art->prefsizey = HEADERY; art->prefsizey = HEADERY;
art->keymapflag = 0; art->keymapflag = 0;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
art->lock = 1;
art->init = spreadsheet_footer_region_init; art->init = spreadsheet_footer_region_init;
art->draw = spreadsheet_footer_region_draw; art->draw = spreadsheet_footer_region_draw;
@ -773,6 +763,7 @@ void ED_spacetype_spreadsheet()
art->regionid = RGN_TYPE_UI; art->regionid = RGN_TYPE_UI;
art->prefsizex = UI_SIDEBAR_PANEL_WIDTH; art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->lock = 1;
art->init = spreadsheet_sidebar_init; art->init = spreadsheet_sidebar_init;
art->layout = ED_region_panels_layout; art->layout = ED_region_panels_layout;
@ -788,6 +779,7 @@ void ED_spacetype_spreadsheet()
art->regionid = RGN_TYPE_TOOLS; art->regionid = RGN_TYPE_TOOLS;
art->prefsizex = 150 + V2D_SCROLL_WIDTH; art->prefsizex = 150 + V2D_SCROLL_WIDTH;
art->keymapflag = ED_KEYMAP_UI; art->keymapflag = ED_KEYMAP_UI;
art->lock = 1;
art->init = ED_region_panels_init; art->init = ED_region_panels_init;
art->draw = spreadsheet_dataset_region_draw; art->draw = spreadsheet_dataset_region_draw;
art->listener = spreadsheet_dataset_region_listener; art->listener = spreadsheet_dataset_region_listener;

View File

@ -237,8 +237,7 @@ static void PREFERENCES_OT_asset_library_remove(wmOperatorType *ot)
static bool associate_blend_poll(bContext *C) static bool associate_blend_poll(bContext *C)
{ {
#ifdef WIN32 #ifdef WIN32
if (BLI_windows_is_store_install()) if (BLI_windows_is_store_install()) {
{
CTX_wm_operator_poll_msg_set(C, "Not available for Microsoft Store installations"); CTX_wm_operator_poll_msg_set(C, "Not available for Microsoft Store installations");
return false; return false;
} }
@ -253,7 +252,8 @@ static int associate_blend_exec(bContext *UNUSED(C), wmOperator *op)
{ {
#ifdef WIN32 #ifdef WIN32
if (BLI_windows_is_store_install()) { if (BLI_windows_is_store_install()) {
BKE_report(op->reports, RPT_ERROR, "Registration not possible from Microsoft Store installations"); BKE_report(
op->reports, RPT_ERROR, "Registration not possible from Microsoft Store installations");
return OPERATOR_CANCELLED; return OPERATOR_CANCELLED;
} }

View File

@ -768,6 +768,7 @@ void applyMouseInput(struct TransInfo *t,
const int mval[2], const int mval[2],
float output[3]); float output[3]);
void transform_input_update(TransInfo *t, const float fac); void transform_input_update(TransInfo *t, const float fac);
void transform_input_virtual_mval_reset(TransInfo *t);
void setCustomPoints(TransInfo *t, MouseInput *mi, const int start[2], const int end[2]); void setCustomPoints(TransInfo *t, MouseInput *mi, const int start[2], const int end[2]);
void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[2]); void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[2]);

View File

@ -494,4 +494,18 @@ void transform_input_update(TransInfo *t, const float fac)
} }
} }
void transform_input_virtual_mval_reset(TransInfo *t)
{
MouseInput *mi = &t->mouse;
if (ELEM(mi->apply, InputAngle, InputAngleSpring)) {
struct InputAngle_Data *data = mi->data;
data->angle = 0.0;
data->mval_prev[0] = mi->imval[0];
data->mval_prev[1] = mi->imval[1];
}
else {
memset(&mi->virtual_mval, 0, sizeof(mi->virtual_mval));
}
}
/** \} */ /** \} */

View File

@ -420,28 +420,42 @@ static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event)
t->context = NULL; t->context = NULL;
/* Allow navigation while transforming. */ /* Allow navigation while transforming. */
if (t->vod && (exit_code & OPERATOR_PASS_THROUGH) && ED_view3d_navigation_do(C, t->vod, event)) { if (t->vod && (exit_code & OPERATOR_PASS_THROUGH)) {
RegionView3D *rv3d = t->region->regiondata; RegionView3D *rv3d = t->region->regiondata;
if (rv3d->rflag & RV3D_NAVIGATING) { const bool is_navigating = (rv3d->rflag & RV3D_NAVIGATING) != 0;
/* Do not update transform while navigating. This can be distracting. */ if (ED_view3d_navigation_do(C, t->vod, event)) {
return OPERATOR_RUNNING_MODAL; if (!is_navigating) {
/* Navigation has started. */
if (t->modifiers & MOD_PRECISION) {
/* WORKAROUND: Remove precision modification, it may have be unintentionally enabled. */
t->modifiers &= ~MOD_PRECISION;
t->mouse.precision = false;
transform_input_virtual_mval_reset(t);
}
}
if (rv3d->rflag & RV3D_NAVIGATING) {
/* Navigation is running. */
/* Do not update transform while navigating. This can be distracting. */
return OPERATOR_RUNNING_MODAL;
}
{
/* Navigation has ended. */
/* Make sure `t->mval` is up to date before calling #transformViewUpdate. */
copy_v2_v2_int(t->mval, event->mval);
/* Call before #applyMouseInput. */
tranformViewUpdate(t);
/* Mouse input is outdated. */
applyMouseInput(t, &t->mouse, t->mval, t->values);
t->redraw |= TREDRAW_HARD;
}
} }
if (t->modifiers & MOD_PRECISION) {
/* Remove Precision modifier, it may have be unintentionally enabled. */
t->modifiers &= ~MOD_PRECISION;
t->mouse.precision = 0;
}
/* Make sure `t->mval` is up to date before calling #transformViewUpdate. */
copy_v2_v2_int(t->mval, event->mval);
/* Call before #applyMouseInput. */
tranformViewUpdate(t);
/* Mouse input is outdated. */
applyMouseInput(t, &t->mouse, t->mval, t->values);
t->redraw |= TREDRAW_HARD;
} }
transformApply(C, t); transformApply(C, t);

View File

@ -413,7 +413,8 @@ void split_edges(Mesh &mesh,
}); });
/* Used for transferring attributes. */ /* Used for transferring attributes. */
Vector<int> new_to_old_edges_map(IndexRange(new_edges.size()).as_span()); Vector<int> new_to_old_edges_map(new_edges.size());
std::iota(new_to_old_edges_map.begin(), new_to_old_edges_map.end(), 0);
/* Step 1: Split the edges. */ /* Step 1: Split the edges. */

View File

@ -1079,7 +1079,7 @@ typedef struct GPUPixelBuffer GPUPixelBuffer;
/** /**
* Creates a #GPUPixelBuffer object with \a byte_size worth of storage. * Creates a #GPUPixelBuffer object with \a byte_size worth of storage.
*/ */
GPUPixelBuffer *GPU_pixel_buffer_create(uint byte_size); GPUPixelBuffer *GPU_pixel_buffer_create(size_t byte_size);
/** /**
* Free a #GPUPixelBuffer object. * Free a #GPUPixelBuffer object.
@ -1104,7 +1104,7 @@ void GPU_pixel_buffer_unmap(GPUPixelBuffer *pixel_buf);
/** /**
* Return size in bytes of the \a pix_buf . * Return size in bytes of the \a pix_buf .
*/ */
uint GPU_pixel_buffer_size(GPUPixelBuffer *pixel_buf); size_t GPU_pixel_buffer_size(GPUPixelBuffer *pixel_buf);
/** /**
* Return the native handle of the \a pix_buf to use for graphic interoperability registration. * Return the native handle of the \a pix_buf to use for graphic interoperability registration.

View File

@ -483,16 +483,26 @@ void GPUCodegen::generate_library()
GPUCodegenCreateInfo &info = *create_info; GPUCodegenCreateInfo &info = *create_info;
void *value; void *value;
/* Iterate over libraries. We need to keep this struct intact in case blender::Vector<std::string> source_files;
* it is required for the optimization pass. */
/* Iterate over libraries. We need to keep this struct intact in case it is required for the
* optimization pass. The first pass just collects the keys from the GSET, given items in a GSET
* are unordered this can cause order differences between invocations, so we collect the keys
* first, and sort them before doing actual work, to guarantee stable behavior while still
* having cheap insertions into the GSET */
GHashIterator *ihash = BLI_ghashIterator_new((GHash *)graph.used_libraries); GHashIterator *ihash = BLI_ghashIterator_new((GHash *)graph.used_libraries);
while (!BLI_ghashIterator_done(ihash)) { while (!BLI_ghashIterator_done(ihash)) {
value = BLI_ghashIterator_getKey(ihash); value = BLI_ghashIterator_getKey(ihash);
auto deps = gpu_shader_dependency_get_resolved_source((const char *)value); source_files.append((const char *)value);
info.dependencies_generated.extend_non_duplicates(deps);
BLI_ghashIterator_step(ihash); BLI_ghashIterator_step(ihash);
} }
BLI_ghashIterator_free(ihash); BLI_ghashIterator_free(ihash);
std::sort(source_files.begin(), source_files.end());
for (auto &key : source_files) {
auto deps = gpu_shader_dependency_get_resolved_source(key.c_str());
info.dependencies_generated.extend_non_duplicates(deps);
}
} }
void GPUCodegen::node_serialize(std::stringstream &eval_ss, const GPUNode *node) void GPUCodegen::node_serialize(std::stringstream &eval_ss, const GPUNode *node)

View File

@ -956,7 +956,7 @@ void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *r_size)
* Pixel buffer utility functions. * Pixel buffer utility functions.
* \{ */ * \{ */
GPUPixelBuffer *GPU_pixel_buffer_create(uint size) GPUPixelBuffer *GPU_pixel_buffer_create(size_t size)
{ {
/* Ensure buffer satisfies the alignment of 256 bytes for copying /* Ensure buffer satisfies the alignment of 256 bytes for copying
* data between buffers and textures. As specified in: * data between buffers and textures. As specified in:
@ -985,7 +985,7 @@ void GPU_pixel_buffer_unmap(GPUPixelBuffer *pix_buf)
reinterpret_cast<PixelBuffer *>(pix_buf)->unmap(); reinterpret_cast<PixelBuffer *>(pix_buf)->unmap();
} }
uint GPU_pixel_buffer_size(GPUPixelBuffer *pix_buf) size_t GPU_pixel_buffer_size(GPUPixelBuffer *pix_buf)
{ {
return reinterpret_cast<PixelBuffer *>(pix_buf)->get_size(); return reinterpret_cast<PixelBuffer *>(pix_buf)->get_size();
} }

View File

@ -336,16 +336,16 @@ static inline const Texture *unwrap(const GPUTexture *vert)
/* GPU pixel Buffer. */ /* GPU pixel Buffer. */
class PixelBuffer { class PixelBuffer {
protected: protected:
uint size_ = 0; size_t size_ = 0;
public: public:
PixelBuffer(uint size) : size_(size){}; PixelBuffer(size_t size) : size_(size){};
virtual ~PixelBuffer(){}; virtual ~PixelBuffer(){};
virtual void *map() = 0; virtual void *map() = 0;
virtual void unmap() = 0; virtual void unmap() = 0;
virtual int64_t get_native_handle() = 0; virtual int64_t get_native_handle() = 0;
virtual uint get_size() = 0; virtual size_t get_size() = 0;
}; };
/* Syntactic sugar. */ /* Syntactic sugar. */

View File

@ -828,7 +828,9 @@ void MTLComputeState::bind_compute_sampler(MTLSamplerBinding &sampler_binding,
} }
} }
void MTLRenderPassState::bind_vertex_buffer(id<MTLBuffer> buffer, uint buffer_offset, uint index) void MTLRenderPassState::bind_vertex_buffer(id<MTLBuffer> buffer,
uint64_t buffer_offset,
uint index)
{ {
BLI_assert(index >= 0 && index < MTL_MAX_BUFFER_BINDINGS); BLI_assert(index >= 0 && index < MTL_MAX_BUFFER_BINDINGS);
BLI_assert(buffer_offset >= 0); BLI_assert(buffer_offset >= 0);
@ -858,7 +860,9 @@ void MTLRenderPassState::bind_vertex_buffer(id<MTLBuffer> buffer, uint buffer_of
} }
} }
void MTLRenderPassState::bind_fragment_buffer(id<MTLBuffer> buffer, uint buffer_offset, uint index) void MTLRenderPassState::bind_fragment_buffer(id<MTLBuffer> buffer,
uint64_t buffer_offset,
uint index)
{ {
BLI_assert(index >= 0 && index < MTL_MAX_BUFFER_BINDINGS); BLI_assert(index >= 0 && index < MTL_MAX_BUFFER_BINDINGS);
BLI_assert(buffer_offset >= 0); BLI_assert(buffer_offset >= 0);
@ -889,7 +893,7 @@ void MTLRenderPassState::bind_fragment_buffer(id<MTLBuffer> buffer, uint buffer_
} }
void MTLComputeState::bind_compute_buffer(id<MTLBuffer> buffer, void MTLComputeState::bind_compute_buffer(id<MTLBuffer> buffer,
uint buffer_offset, uint64_t buffer_offset,
uint index, uint index,
bool writeable) bool writeable)
{ {
@ -924,7 +928,7 @@ void MTLComputeState::bind_compute_buffer(id<MTLBuffer> buffer,
} }
} }
void MTLRenderPassState::bind_vertex_bytes(void *bytes, uint length, uint index) void MTLRenderPassState::bind_vertex_bytes(void *bytes, uint64_t length, uint index)
{ {
/* Bytes always updated as source data may have changed. */ /* Bytes always updated as source data may have changed. */
BLI_assert(index >= 0 && index < MTL_MAX_BUFFER_BINDINGS); BLI_assert(index >= 0 && index < MTL_MAX_BUFFER_BINDINGS);
@ -949,7 +953,7 @@ void MTLRenderPassState::bind_vertex_bytes(void *bytes, uint length, uint index)
this->cached_vertex_buffer_bindings[index].offset = -1; this->cached_vertex_buffer_bindings[index].offset = -1;
} }
void MTLRenderPassState::bind_fragment_bytes(void *bytes, uint length, uint index) void MTLRenderPassState::bind_fragment_bytes(void *bytes, uint64_t length, uint index)
{ {
/* Bytes always updated as source data may have changed. */ /* Bytes always updated as source data may have changed. */
BLI_assert(index >= 0 && index < MTL_MAX_BUFFER_BINDINGS); BLI_assert(index >= 0 && index < MTL_MAX_BUFFER_BINDINGS);
@ -974,7 +978,7 @@ void MTLRenderPassState::bind_fragment_bytes(void *bytes, uint length, uint inde
this->cached_fragment_buffer_bindings[index].offset = -1; this->cached_fragment_buffer_bindings[index].offset = -1;
} }
void MTLComputeState::bind_compute_bytes(void *bytes, uint length, uint index) void MTLComputeState::bind_compute_bytes(void *bytes, uint64_t length, uint index)
{ {
/* Bytes always updated as source data may have changed. */ /* Bytes always updated as source data may have changed. */
BLI_assert(index >= 0 && index < MTL_MAX_BUFFER_BINDINGS); BLI_assert(index >= 0 && index < MTL_MAX_BUFFER_BINDINGS);

View File

@ -86,7 +86,7 @@ struct BufferBindingCached {
* or an MTLBuffer. */ * or an MTLBuffer. */
bool is_bytes; bool is_bytes;
id<MTLBuffer> metal_buffer; id<MTLBuffer> metal_buffer;
int offset; uint64_t offset;
}; };
/* Caching of CommandEncoder textures bindings. */ /* Caching of CommandEncoder textures bindings. */
@ -144,10 +144,10 @@ class MTLRenderPassState {
uint slot); uint slot);
/* Buffer binding (RenderCommandEncoder). */ /* Buffer binding (RenderCommandEncoder). */
void bind_vertex_buffer(id<MTLBuffer> buffer, uint buffer_offset, uint index); void bind_vertex_buffer(id<MTLBuffer> buffer, uint64_t buffer_offset, uint index);
void bind_fragment_buffer(id<MTLBuffer> buffer, uint buffer_offset, uint index); void bind_fragment_buffer(id<MTLBuffer> buffer, uint64_t buffer_offset, uint index);
void bind_vertex_bytes(void *bytes, uint length, uint index); void bind_vertex_bytes(void *bytes, uint64_t length, uint index);
void bind_fragment_bytes(void *bytes, uint length, uint index); void bind_fragment_bytes(void *bytes, uint64_t length, uint index);
}; };
/* Metal Context Compute Pass State -- Used to track active ComputeCommandEncoder state. */ /* Metal Context Compute Pass State -- Used to track active ComputeCommandEncoder state. */
@ -182,10 +182,10 @@ class MTLComputeState {
uint slot); uint slot);
/* Buffer binding (ComputeCommandEncoder). */ /* Buffer binding (ComputeCommandEncoder). */
void bind_compute_buffer(id<MTLBuffer> buffer, void bind_compute_buffer(id<MTLBuffer> buffer,
uint buffer_offset, uint64_t buffer_offset,
uint index, uint index,
bool writeable = false); bool writeable = false);
void bind_compute_bytes(void *bytes, uint length, uint index); void bind_compute_bytes(void *bytes, uint64_t length, uint index);
}; };
/* Depth Stencil State */ /* Depth Stencil State */

View File

@ -1148,7 +1148,7 @@ bool MTLContext::ensure_buffer_bindings(
/* buffer(N) index of where to bind the UBO. */ /* buffer(N) index of where to bind the UBO. */
const uint32_t buffer_index = ubo.buffer_index; const uint32_t buffer_index = ubo.buffer_index;
id<MTLBuffer> ubo_buffer = nil; id<MTLBuffer> ubo_buffer = nil;
int ubo_size = 0; size_t ubo_size = 0;
bool bind_dummy_buffer = false; bool bind_dummy_buffer = false;
if (this->pipeline_state.ubo_bindings[ubo_location].bound) { if (this->pipeline_state.ubo_bindings[ubo_location].bound) {
@ -1196,7 +1196,7 @@ bool MTLContext::ensure_buffer_bindings(
if (ubo_size < expected_size) { if (ubo_size < expected_size) {
MTL_LOG_UBO_ERROR( MTL_LOG_UBO_ERROR(
"[Error][UBO] UBO (UBO Name: %s) bound at location: %d (buffer[[%d]]) with size " "[Error][UBO] UBO (UBO Name: %s) bound at location: %d (buffer[[%d]]) with size "
"%d (Expected size " "%lu (Expected size "
"%d) (Shader Name: %s) is too small -- binding NULL buffer. This is likely an " "%d) (Shader Name: %s) is too small -- binding NULL buffer. This is likely an "
"over-binding, which is not used, but we need this to avoid validation " "over-binding, which is not used, but we need this to avoid validation "
"issues\n", "issues\n",
@ -1270,7 +1270,7 @@ bool MTLContext::ensure_buffer_bindings(
/* buffer(N) index of where to bind the SSBO. */ /* buffer(N) index of where to bind the SSBO. */
const uint32_t buffer_index = ssbo.buffer_index; const uint32_t buffer_index = ssbo.buffer_index;
id<MTLBuffer> ssbo_buffer = nil; id<MTLBuffer> ssbo_buffer = nil;
int ssbo_size = 0; size_t ssbo_size = 0;
UNUSED_VARS_NDEBUG(ssbo_size); UNUSED_VARS_NDEBUG(ssbo_size);
if (this->pipeline_state.ssbo_bindings[ssbo_location].bound) { if (this->pipeline_state.ssbo_bindings[ssbo_location].bound) {
@ -1378,7 +1378,7 @@ bool MTLContext::ensure_buffer_bindings(
/* buffer(N) index of where to bind the UBO. */ /* buffer(N) index of where to bind the UBO. */
const uint32_t buffer_index = ubo.buffer_index; const uint32_t buffer_index = ubo.buffer_index;
id<MTLBuffer> ubo_buffer = nil; id<MTLBuffer> ubo_buffer = nil;
int ubo_size = 0; size_t ubo_size = 0;
bool bind_dummy_buffer = false; bool bind_dummy_buffer = false;
if (this->pipeline_state.ubo_bindings[ubo_location].bound) { if (this->pipeline_state.ubo_bindings[ubo_location].bound) {
@ -1700,12 +1700,12 @@ void MTLContext::ensure_texture_bindings(
} }
else { else {
/* Populate argument buffer with current global sampler bindings. */ /* Populate argument buffer with current global sampler bindings. */
int size = [argument_encoder encodedLength]; size_t size = [argument_encoder encodedLength];
int alignment = max_uu([argument_encoder alignment], 256); size_t alignment = max_uu([argument_encoder alignment], 256);
int size_align_delta = (size % alignment); size_t size_align_delta = (size % alignment);
int aligned_alloc_size = ((alignment > 1) && (size_align_delta > 0)) ? size_t aligned_alloc_size = ((alignment > 1) && (size_align_delta > 0)) ?
size + (alignment - (size % alignment)) : size + (alignment - (size % alignment)) :
size; size;
/* Allocate buffer to store encoded sampler arguments. */ /* Allocate buffer to store encoded sampler arguments. */
encoder_buffer = MTLContext::get_global_memory_manager()->allocate(aligned_alloc_size, encoder_buffer = MTLContext::get_global_memory_manager()->allocate(aligned_alloc_size,
@ -1921,12 +1921,12 @@ void MTLContext::ensure_texture_bindings(
} }
else { else {
/* Populate argument buffer with current global sampler bindings. */ /* Populate argument buffer with current global sampler bindings. */
int size = [argument_encoder encodedLength]; size_t size = [argument_encoder encodedLength];
int alignment = max_uu([argument_encoder alignment], 256); size_t alignment = max_uu([argument_encoder alignment], 256);
int size_align_delta = (size % alignment); size_t size_align_delta = (size % alignment);
int aligned_alloc_size = ((alignment > 1) && (size_align_delta > 0)) ? size_t aligned_alloc_size = ((alignment > 1) && (size_align_delta > 0)) ?
size + (alignment - (size % alignment)) : size + (alignment - (size % alignment)) :
size; size;
/* Allocate buffer to store encoded sampler arguments. */ /* Allocate buffer to store encoded sampler arguments. */
encoder_buffer = MTLContext::get_global_memory_manager()->allocate(aligned_alloc_size, encoder_buffer = MTLContext::get_global_memory_manager()->allocate(aligned_alloc_size,

View File

@ -494,7 +494,7 @@ void MTLFrameBuffer::read(eGPUFrameBufferBits planes,
if (tex) { if (tex) {
size_t sample_len = area[2] * area[3]; size_t sample_len = area[2] * area[3];
size_t sample_size = to_bytesize(tex->format_, format); size_t sample_size = to_bytesize(tex->format_, format);
int debug_data_size = sample_len * sample_size; size_t debug_data_size = sample_len * sample_size;
tex->read_internal(0, tex->read_internal(0,
area[0], area[0],
area[1], area[1],
@ -523,7 +523,7 @@ void MTLFrameBuffer::read(eGPUFrameBufferBits planes,
if (tex) { if (tex) {
size_t sample_len = area[2] * area[3]; size_t sample_len = area[2] * area[3];
size_t sample_size = to_bytesize(tex->format_, format); size_t sample_size = to_bytesize(tex->format_, format);
int debug_data_size = sample_len * sample_size * channel_len; size_t debug_data_size = sample_len * sample_size * channel_len;
tex->read_internal(0, tex->read_internal(0,
area[0], area[0],
area[1], area[1],

View File

@ -322,7 +322,7 @@ void MTLImmediate::end()
@autoreleasepool { @autoreleasepool {
id<MTLBuffer> index_buffer_mtl = nil; id<MTLBuffer> index_buffer_mtl = nil;
uint32_t index_buffer_offset = 0; uint64_t index_buffer_offset = 0;
/* Region of scratch buffer used for topology emulation element data. /* Region of scratch buffer used for topology emulation element data.
* NOTE(Metal): We do not need to manually flush as the entire scratch * NOTE(Metal): We do not need to manually flush as the entire scratch

View File

@ -777,7 +777,7 @@ MTLTemporaryBuffer MTLCircularBuffer::allocate_range_aligned(uint64_t alloc_size
/* Ensure alignment of an allocation is aligned to compatible offset boundaries. */ /* Ensure alignment of an allocation is aligned to compatible offset boundaries. */
BLI_assert(alignment > 0); BLI_assert(alignment > 0);
alignment = max_ulul(alignment, 256); alignment = max_uu(alignment, 256);
/* Align current offset and allocation size to desired alignment */ /* Align current offset and allocation size to desired alignment */
uint64_t aligned_current_offset = ceil_to_multiple_ul(current_offset_, alignment); uint64_t aligned_current_offset = ceil_to_multiple_ul(current_offset_, alignment);

View File

@ -71,7 +71,7 @@ class MTLStorageBuf : public StorageBuf {
void init(); void init();
id<MTLBuffer> get_metal_buffer(); id<MTLBuffer> get_metal_buffer();
int get_size(); size_t get_size();
const char *get_name() const char *get_name()
{ {
return name_; return name_;

View File

@ -296,7 +296,7 @@ id<MTLBuffer> MTLStorageBuf::get_metal_buffer()
return source_buffer->get_metal_buffer(); return source_buffer->get_metal_buffer();
} }
int MTLStorageBuf::get_size() size_t MTLStorageBuf::get_size()
{ {
BLI_assert(this); BLI_assert(this);
return size_in_bytes_; return size_in_bytes_;

View File

@ -184,7 +184,7 @@ class MTLTexture : public Texture {
/* Texture Storage. */ /* Texture Storage. */
id<MTLBuffer> texture_buffer_ = nil; id<MTLBuffer> texture_buffer_ = nil;
uint aligned_w_ = 0; size_t aligned_w_ = 0;
/* Blit Frame-buffer. */ /* Blit Frame-buffer. */
GPUFrameBuffer *blit_fb_ = nullptr; GPUFrameBuffer *blit_fb_ = nullptr;
@ -313,7 +313,7 @@ class MTLTexture : public Texture {
int depth, int depth,
eGPUDataFormat desired_output_format, eGPUDataFormat desired_output_format,
int num_output_components, int num_output_components,
int debug_data_size, size_t debug_data_size,
void *r_data); void *r_data);
void bake_mip_swizzle_view(); void bake_mip_swizzle_view();
@ -452,7 +452,7 @@ class MTLPixelBuffer : public PixelBuffer {
void *map() override; void *map() override;
void unmap() override; void unmap() override;
int64_t get_native_handle() override; int64_t get_native_handle() override;
uint get_size() override; size_t get_size() override;
id<MTLBuffer> get_metal_buffer(); id<MTLBuffer> get_metal_buffer();
@ -461,7 +461,7 @@ class MTLPixelBuffer : public PixelBuffer {
/* Utility */ /* Utility */
MTLPixelFormat gpu_texture_format_to_metal(eGPUTextureFormat tex_format); MTLPixelFormat gpu_texture_format_to_metal(eGPUTextureFormat tex_format);
int get_mtl_format_bytesize(MTLPixelFormat tex_format); size_t get_mtl_format_bytesize(MTLPixelFormat tex_format);
int get_mtl_format_num_components(MTLPixelFormat tex_format); int get_mtl_format_num_components(MTLPixelFormat tex_format);
bool mtl_format_supports_blending(MTLPixelFormat format); bool mtl_format_supports_blending(MTLPixelFormat format);

View File

@ -81,7 +81,7 @@ gpu::MTLTexture::MTLTexture(const char *name,
BLI_assert(metal_texture != nil); BLI_assert(metal_texture != nil);
BLI_assert(type == GPU_TEXTURE_2D); BLI_assert(type == GPU_TEXTURE_2D);
type_ = type; type_ = type;
init_2D(metal_texture.width, metal_texture.height, 0, 1, format); init_2D((int)metal_texture.width, (int)metal_texture.height, 0, 1, format);
/* Assign MTLTexture. */ /* Assign MTLTexture. */
texture_ = metal_texture; texture_ = metal_texture;
@ -181,7 +181,7 @@ void gpu::MTLTexture::bake_mip_swizzle_view()
MTLTextureType texture_view_texture_type = to_metal_type(type_); MTLTextureType texture_view_texture_type = to_metal_type(type_);
int range_len = min_ii((mip_texture_max_level_ - mip_texture_base_level_) + 1, int range_len = min_ii((mip_texture_max_level_ - mip_texture_base_level_) + 1,
texture_.mipmapLevelCount - mip_texture_base_level_); (int)texture_.mipmapLevelCount - mip_texture_base_level_);
BLI_assert(range_len > 0); BLI_assert(range_len > 0);
BLI_assert(mip_texture_base_level_ < texture_.mipmapLevelCount); BLI_assert(mip_texture_base_level_ < texture_.mipmapLevelCount);
BLI_assert(mip_texture_base_layer_ < num_slices); BLI_assert(mip_texture_base_layer_ < num_slices);
@ -194,7 +194,7 @@ void gpu::MTLTexture::bake_mip_swizzle_view()
MTL_LOG_INFO( MTL_LOG_INFO(
"Updating texture view - MIP TEXTURE BASE LEVEL: %d, MAX LEVEL: %d (Range len: %d)\n", "Updating texture view - MIP TEXTURE BASE LEVEL: %d, MAX LEVEL: %d (Range len: %d)\n",
mip_texture_base_level_, mip_texture_base_level_,
min_ii(mip_texture_max_level_, texture_.mipmapLevelCount), min_ii(mip_texture_max_level_, (int)texture_.mipmapLevelCount),
range_len); range_len);
mip_swizzle_view_.label = [texture_ label]; mip_swizzle_view_.label = [texture_ label];
texture_view_dirty_flags_ = TEXTURE_VIEW_NOT_DIRTY; texture_view_dirty_flags_ = TEXTURE_VIEW_NOT_DIRTY;
@ -493,25 +493,26 @@ void gpu::MTLTexture::update_sub(
@autoreleasepool { @autoreleasepool {
/* Determine totalsize of INPUT Data. */ /* Determine totalsize of INPUT Data. */
int num_channels = to_component_len(format_); int num_channels = to_component_len(format_);
int input_bytes_per_pixel = to_bytesize(format_, type); size_t input_bytes_per_pixel = to_bytesize(format_, type);
int totalsize = 0; size_t totalsize = 0;
/* If unpack row length is used, size of input data uses the unpack row length, rather than the /* If unpack row length is used, size of input data uses the unpack row length, rather than the
* image length. */ * image length. */
int expected_update_w = ((ctx->pipeline_state.unpack_row_length == 0) ? size_t expected_update_w = ((ctx->pipeline_state.unpack_row_length == 0) ?
extent[0] : extent[0] :
ctx->pipeline_state.unpack_row_length); ctx->pipeline_state.unpack_row_length);
/* Ensure calculated total size isn't larger than remaining image data size */ /* Ensure calculated total size isn't larger than remaining image data size */
switch (this->dimensions_count()) { switch (this->dimensions_count()) {
case 1: case 1:
totalsize = input_bytes_per_pixel * max_ii(expected_update_w, 1); totalsize = input_bytes_per_pixel * max_ulul(expected_update_w, 1);
break; break;
case 2: case 2:
totalsize = input_bytes_per_pixel * max_ii(expected_update_w, 1) * extent[1]; totalsize = input_bytes_per_pixel * max_ulul(expected_update_w, 1) * (size_t)extent[1];
break; break;
case 3: case 3:
totalsize = input_bytes_per_pixel * max_ii(expected_update_w, 1) * extent[1] * extent[2]; totalsize = input_bytes_per_pixel * max_ulul(expected_update_w, 1) * (size_t)extent[1] *
(size_t)extent[2];
break; break;
default: default:
BLI_assert(false); BLI_assert(false);
@ -543,7 +544,7 @@ void gpu::MTLTexture::update_sub(
/* Determine expected destination data size. */ /* Determine expected destination data size. */
MTLPixelFormat destination_format = gpu_texture_format_to_metal(format_); MTLPixelFormat destination_format = gpu_texture_format_to_metal(format_);
int expected_dst_bytes_per_pixel = get_mtl_format_bytesize(destination_format); size_t expected_dst_bytes_per_pixel = get_mtl_format_bytesize(destination_format);
int destination_num_channels = get_mtl_format_num_components(destination_format); int destination_num_channels = get_mtl_format_num_components(destination_format);
/* Prepare specialization struct (For texture update routine). */ /* Prepare specialization struct (For texture update routine). */
@ -588,8 +589,8 @@ void gpu::MTLTexture::update_sub(
/* Debug and verification. */ /* Debug and verification. */
if (!can_use_direct_blit) { if (!can_use_direct_blit) {
MTL_LOG_WARNING( MTL_LOG_WARNING(
"gpu::MTLTexture::update_sub supplied bpp is %d bytes (%d components per " "gpu::MTLTexture::update_sub supplied bpp is %lu bytes (%d components per "
"pixel), but backing texture bpp is %d bytes (%d components per pixel) " "pixel), but backing texture bpp is %lu bytes (%d components per pixel) "
"(TODO(Metal): Channel Conversion needed) (w: %d, h: %d, d: %d)\n", "(TODO(Metal): Channel Conversion needed) (w: %d, h: %d, d: %d)\n",
input_bytes_per_pixel, input_bytes_per_pixel,
num_channels, num_channels,
@ -708,15 +709,15 @@ void gpu::MTLTexture::update_sub(
case GPU_TEXTURE_1D_ARRAY: { case GPU_TEXTURE_1D_ARRAY: {
if (can_use_direct_blit) { if (can_use_direct_blit) {
/* Use Blit based update. */ /* Use Blit based update. */
int bytes_per_row = expected_dst_bytes_per_pixel * size_t bytes_per_row = expected_dst_bytes_per_pixel *
((ctx->pipeline_state.unpack_row_length == 0) ? ((ctx->pipeline_state.unpack_row_length == 0) ?
extent[0] : extent[0] :
ctx->pipeline_state.unpack_row_length); ctx->pipeline_state.unpack_row_length);
int bytes_per_image = bytes_per_row; size_t bytes_per_image = bytes_per_row;
int max_array_index = ((type_ == GPU_TEXTURE_1D_ARRAY) ? extent[1] : 1); int max_array_index = ((type_ == GPU_TEXTURE_1D_ARRAY) ? extent[1] : 1);
for (int array_index = 0; array_index < max_array_index; array_index++) { for (int array_index = 0; array_index < max_array_index; array_index++) {
int buffer_array_offset = (bytes_per_image * array_index); size_t buffer_array_offset = (bytes_per_image * (size_t)array_index);
[blit_encoder [blit_encoder
copyFromBuffer:staging_buffer copyFromBuffer:staging_buffer
sourceOffset:buffer_array_offset sourceOffset:buffer_array_offset
@ -780,13 +781,13 @@ void gpu::MTLTexture::update_sub(
case GPU_TEXTURE_2D_ARRAY: { case GPU_TEXTURE_2D_ARRAY: {
if (can_use_direct_blit) { if (can_use_direct_blit) {
/* Use Blit encoder update. */ /* Use Blit encoder update. */
int bytes_per_row = expected_dst_bytes_per_pixel * size_t bytes_per_row = expected_dst_bytes_per_pixel *
((ctx->pipeline_state.unpack_row_length == 0) ? ((ctx->pipeline_state.unpack_row_length == 0) ?
extent[0] : extent[0] :
ctx->pipeline_state.unpack_row_length); ctx->pipeline_state.unpack_row_length);
int bytes_per_image = bytes_per_row * extent[1]; size_t bytes_per_image = bytes_per_row * extent[1];
int texture_array_relative_offset = 0; size_t texture_array_relative_offset = 0;
int base_slice = (type_ == GPU_TEXTURE_2D_ARRAY) ? offset[2] : 0; int base_slice = (type_ == GPU_TEXTURE_2D_ARRAY) ? offset[2] : 0;
int final_slice = base_slice + ((type_ == GPU_TEXTURE_2D_ARRAY) ? extent[2] : 1); int final_slice = base_slice + ((type_ == GPU_TEXTURE_2D_ARRAY) ? extent[2] : 1);
@ -861,11 +862,11 @@ void gpu::MTLTexture::update_sub(
/* 3D */ /* 3D */
case GPU_TEXTURE_3D: { case GPU_TEXTURE_3D: {
if (can_use_direct_blit) { if (can_use_direct_blit) {
int bytes_per_row = expected_dst_bytes_per_pixel * size_t bytes_per_row = expected_dst_bytes_per_pixel *
((ctx->pipeline_state.unpack_row_length == 0) ? ((ctx->pipeline_state.unpack_row_length == 0) ?
extent[0] : extent[0] :
ctx->pipeline_state.unpack_row_length); ctx->pipeline_state.unpack_row_length);
int bytes_per_image = bytes_per_row * extent[1]; size_t bytes_per_image = bytes_per_row * extent[1];
[blit_encoder copyFromBuffer:staging_buffer [blit_encoder copyFromBuffer:staging_buffer
sourceOffset:0 sourceOffset:0
sourceBytesPerRow:bytes_per_row sourceBytesPerRow:bytes_per_row
@ -902,13 +903,12 @@ void gpu::MTLTexture::update_sub(
/* CUBE */ /* CUBE */
case GPU_TEXTURE_CUBE: { case GPU_TEXTURE_CUBE: {
if (can_use_direct_blit) { if (can_use_direct_blit) {
int bytes_per_row = expected_dst_bytes_per_pixel * size_t bytes_per_row = expected_dst_bytes_per_pixel *
((ctx->pipeline_state.unpack_row_length == 0) ? ((ctx->pipeline_state.unpack_row_length == 0) ?
extent[0] : extent[0] :
ctx->pipeline_state.unpack_row_length); ctx->pipeline_state.unpack_row_length);
int bytes_per_image = bytes_per_row * extent[1]; size_t bytes_per_image = bytes_per_row * extent[1];
size_t texture_array_relative_offset = 0;
int texture_array_relative_offset = 0;
/* Iterate over all cube faces in range (offset[2], offset[2] + extent[2]). */ /* Iterate over all cube faces in range (offset[2], offset[2] + extent[2]). */
for (int i = 0; i < extent[2]; i++) { for (int i = 0; i < extent[2]; i++) {
@ -938,14 +938,14 @@ void gpu::MTLTexture::update_sub(
case GPU_TEXTURE_CUBE_ARRAY: { case GPU_TEXTURE_CUBE_ARRAY: {
if (can_use_direct_blit) { if (can_use_direct_blit) {
int bytes_per_row = expected_dst_bytes_per_pixel * size_t bytes_per_row = expected_dst_bytes_per_pixel *
((ctx->pipeline_state.unpack_row_length == 0) ? ((ctx->pipeline_state.unpack_row_length == 0) ?
extent[0] : extent[0] :
ctx->pipeline_state.unpack_row_length); ctx->pipeline_state.unpack_row_length);
int bytes_per_image = bytes_per_row * extent[1]; size_t bytes_per_image = bytes_per_row * extent[1];
/* Upload to all faces between offset[2] (which is zero in most cases) AND extent[2]. */ /* Upload to all faces between offset[2] (which is zero in most cases) AND extent[2]. */
int texture_array_relative_offset = 0; size_t texture_array_relative_offset = 0;
for (int i = 0; i < extent[2]; i++) { for (int i = 0; i < extent[2]; i++) {
int face_index = offset[2] + i; int face_index = offset[2] + i;
[blit_encoder copyFromBuffer:staging_buffer [blit_encoder copyFromBuffer:staging_buffer
@ -1112,9 +1112,9 @@ void MTLTexture::update_sub(int offset[3],
/* Calculate dimensions. */ /* Calculate dimensions. */
int num_image_channels = to_component_len(format_); int num_image_channels = to_component_len(format_);
uint bits_per_pixel = num_image_channels * to_bytesize(format); size_t bits_per_pixel = num_image_channels * to_bytesize(format);
uint bytes_per_row = bits_per_pixel * extent[0]; size_t bytes_per_row = bits_per_pixel * extent[0];
uint bytes_per_image = bytes_per_row * extent[1]; size_t bytes_per_image = bytes_per_row * extent[1];
/* Currently only required for 2D textures. */ /* Currently only required for 2D textures. */
if (type_ == GPU_TEXTURE_2D) { if (type_ == GPU_TEXTURE_2D) {
@ -1414,7 +1414,7 @@ void gpu::MTLTexture::read_internal(int mip,
int depth, int depth,
eGPUDataFormat desired_output_format, eGPUDataFormat desired_output_format,
int num_output_components, int num_output_components,
int debug_data_size, size_t debug_data_size,
void *r_data) void *r_data)
{ {
/* Verify textures are baked. */ /* Verify textures are baked. */
@ -1429,10 +1429,10 @@ void gpu::MTLTexture::read_internal(int mip,
/* Calculate Desired output size. */ /* Calculate Desired output size. */
int num_channels = to_component_len(format_); int num_channels = to_component_len(format_);
BLI_assert(num_output_components <= num_channels); BLI_assert(num_output_components <= num_channels);
uint desired_output_bpp = num_output_components * to_bytesize(desired_output_format); size_t desired_output_bpp = num_output_components * to_bytesize(desired_output_format);
/* Calculate Metal data output for trivial copy. */ /* Calculate Metal data output for trivial copy. */
uint image_bpp = get_mtl_format_bytesize(texture_.pixelFormat); size_t image_bpp = get_mtl_format_bytesize(texture_.pixelFormat);
uint image_components = get_mtl_format_num_components(texture_.pixelFormat); uint image_components = get_mtl_format_num_components(texture_.pixelFormat);
bool is_depth_format = (format_flag_ & GPU_FORMAT_DEPTH); bool is_depth_format = (format_flag_ & GPU_FORMAT_DEPTH);
@ -1470,9 +1470,9 @@ void gpu::MTLTexture::read_internal(int mip,
} }
/* Determine size of output data. */ /* Determine size of output data. */
uint bytes_per_row = desired_output_bpp * width; size_t bytes_per_row = desired_output_bpp * width;
uint bytes_per_image = bytes_per_row * height; size_t bytes_per_image = bytes_per_row * height;
uint total_bytes = bytes_per_image * depth; size_t total_bytes = bytes_per_image * depth;
if (can_use_simple_read) { if (can_use_simple_read) {
/* DEBUG check that if direct copy is being used, then both the expected output size matches /* DEBUG check that if direct copy is being used, then both the expected output size matches
@ -1589,7 +1589,7 @@ void gpu::MTLTexture::read_internal(int mip,
} }
int base_slice = z_off; int base_slice = z_off;
int final_slice = base_slice + depth; int final_slice = base_slice + depth;
int texture_array_relative_offset = 0; size_t texture_array_relative_offset = 0;
for (int array_slice = base_slice; array_slice < final_slice; array_slice++) { for (int array_slice = base_slice; array_slice < final_slice; array_slice++) {
[enc copyFromTexture:read_texture [enc copyFromTexture:read_texture
@ -1639,7 +1639,7 @@ void gpu::MTLTexture::read_internal(int mip,
} }
int base_slice = z_off; int base_slice = z_off;
int final_slice = base_slice + depth; int final_slice = base_slice + depth;
int texture_array_relative_offset = 0; size_t texture_array_relative_offset = 0;
for (int array_slice = base_slice; array_slice < final_slice; array_slice++) { for (int array_slice = base_slice; array_slice < final_slice; array_slice++) {
[enc copyFromTexture:read_texture [enc copyFromTexture:read_texture
@ -1686,12 +1686,12 @@ void gpu::MTLTexture::read_internal(int mip,
/* Copy data from Shared Memory into ptr. */ /* Copy data from Shared Memory into ptr. */
memcpy(r_data, destination_buffer_host_ptr, total_bytes); memcpy(r_data, destination_buffer_host_ptr, total_bytes);
MTL_LOG_INFO("gpu::MTLTexture::read_internal success! %d bytes read\n", total_bytes); MTL_LOG_INFO("gpu::MTLTexture::read_internal success! %lu bytes read\n", total_bytes);
} }
else { else {
MTL_LOG_WARNING( MTL_LOG_WARNING(
"[Warning] gpu::MTLTexture::read_internal not yet supported for this config -- data " "[Warning] gpu::MTLTexture::read_internal not yet supported for this config -- data "
"format different (src %d bytes, dst %d bytes) (src format: %d, dst format: %d), or " "format different (src %lu bytes, dst %lu bytes) (src format: %d, dst format: %d), or "
"varying component counts (src %d, dst %d)\n", "varying component counts (src %d, dst %d)\n",
image_bpp, image_bpp,
desired_output_bpp, desired_output_bpp,
@ -1752,8 +1752,8 @@ bool gpu::MTLTexture::init_internal(GPUVertBuf *vbo)
/* Verify Texture and vertex buffer alignment. */ /* Verify Texture and vertex buffer alignment. */
const GPUVertFormat *format = GPU_vertbuf_get_format(vbo); const GPUVertFormat *format = GPU_vertbuf_get_format(vbo);
int bytes_per_pixel = get_mtl_format_bytesize(mtl_format); size_t bytes_per_pixel = get_mtl_format_bytesize(mtl_format);
int bytes_per_row = bytes_per_pixel * w_; size_t bytes_per_row = bytes_per_pixel * w_;
MTLContext *mtl_ctx = MTLContext::get(); MTLContext *mtl_ctx = MTLContext::get();
uint32_t align_requirement = static_cast<uint32_t>( uint32_t align_requirement = static_cast<uint32_t>(
@ -1815,7 +1815,7 @@ bool gpu::MTLTexture::init_internal(GPUVertBuf *vbo)
texture_ = [source_buffer texture_ = [source_buffer
newTextureWithDescriptor:texture_descriptor_ newTextureWithDescriptor:texture_descriptor_
offset:0 offset:0
bytesPerRow:ceil_to_multiple_u(bytes_per_row, align_requirement)]; bytesPerRow:ceil_to_multiple_ul(bytes_per_row, align_requirement)];
aligned_w_ = bytes_per_row / bytes_per_pixel; aligned_w_ = bytes_per_row / bytes_per_pixel;
BLI_assert(texture_); BLI_assert(texture_);
@ -2190,7 +2190,7 @@ int64_t MTLPixelBuffer::get_native_handle()
return reinterpret_cast<int64_t>(buffer_); return reinterpret_cast<int64_t>(buffer_);
} }
uint MTLPixelBuffer::get_size() size_t MTLPixelBuffer::get_size()
{ {
return size_; return size_;
} }

View File

@ -185,7 +185,7 @@ MTLPixelFormat gpu_texture_format_to_metal(eGPUTextureFormat tex_format)
return MTLPixelFormatRGBA8Unorm; return MTLPixelFormatRGBA8Unorm;
} }
int get_mtl_format_bytesize(MTLPixelFormat tex_format) size_t get_mtl_format_bytesize(MTLPixelFormat tex_format)
{ {
switch (tex_format) { switch (tex_format) {
case MTLPixelFormatRGBA8Uint: case MTLPixelFormatRGBA8Uint:

View File

@ -47,7 +47,7 @@ class MTLUniformBuf : public UniformBuf {
void clear_to_zero() override; void clear_to_zero() override;
id<MTLBuffer> get_metal_buffer(); id<MTLBuffer> get_metal_buffer();
int get_size(); size_t get_size();
const char *get_name() const char *get_name()
{ {
return name_; return name_;

View File

@ -190,7 +190,7 @@ id<MTLBuffer> MTLUniformBuf::get_metal_buffer()
return nil; return nil;
} }
int MTLUniformBuf::get_size() size_t MTLUniformBuf::get_size()
{ {
BLI_assert(this); BLI_assert(this);
return size_in_bytes_; return size_in_bytes_;

View File

@ -75,7 +75,7 @@ void MTLVertBuf::duplicate_data(VertBuf *dst_)
BLI_assert(dst->vbo_ == nullptr); BLI_assert(dst->vbo_ == nullptr);
/* Allocate VBO for destination vertbuf. */ /* Allocate VBO for destination vertbuf. */
uint length = src->vbo_->get_size(); uint64_t length = src->vbo_->get_size();
dst->vbo_ = MTLContext::get_global_memory_manager()->allocate( dst->vbo_ = MTLContext::get_global_memory_manager()->allocate(
length, (dst->get_usage_type() != GPU_USAGE_DEVICE_ONLY)); length, (dst->get_usage_type() != GPU_USAGE_DEVICE_ONLY));
dst->alloc_size_ = length; dst->alloc_size_ = length;
@ -225,7 +225,7 @@ void MTLVertBuf::bind()
sourceOffset:0 sourceOffset:0
toBuffer:copy_new_buffer toBuffer:copy_new_buffer
destinationOffset:0 destinationOffset:0
size:min_ii([copy_new_buffer length], [copy_prev_buffer length])]; size:min_ulul([copy_new_buffer length], [copy_prev_buffer length])];
/* Flush newly copied data back to host-side buffer, if one exists. /* Flush newly copied data back to host-side buffer, if one exists.
* Ensures data and cache coherency for managed MTLBuffers. */ * Ensures data and cache coherency for managed MTLBuffers. */
@ -274,7 +274,7 @@ void MTLVertBuf::update_sub(uint start, uint len, const void *data)
[scratch_allocation.metal_buffer [scratch_allocation.metal_buffer
didModifyRange:NSMakeRange(scratch_allocation.buffer_offset, len)]; didModifyRange:NSMakeRange(scratch_allocation.buffer_offset, len)];
id<MTLBuffer> data_buffer = scratch_allocation.metal_buffer; id<MTLBuffer> data_buffer = scratch_allocation.metal_buffer;
uint data_buffer_offset = scratch_allocation.buffer_offset; uint64_t data_buffer_offset = scratch_allocation.buffer_offset;
BLI_assert(vbo_ != nullptr && data != nullptr); BLI_assert(vbo_ != nullptr && data != nullptr);
BLI_assert((start + len) <= vbo_->get_size()); BLI_assert((start + len) <= vbo_->get_size());

View File

@ -891,7 +891,7 @@ int64_t GLPixelBuffer::get_native_handle()
return int64_t(gl_id_); return int64_t(gl_id_);
} }
uint GLPixelBuffer::get_size() size_t GLPixelBuffer::get_size()
{ {
return size_; return size_;
} }

View File

@ -139,7 +139,7 @@ class GLPixelBuffer : public PixelBuffer {
void *map() override; void *map() override;
void unmap() override; void unmap() override;
int64_t get_native_handle() override; int64_t get_native_handle() override;
uint get_size() override; size_t get_size() override;
MEM_CXX_CLASS_ALLOC_FUNCS("GLPixelBuffer") MEM_CXX_CLASS_ALLOC_FUNCS("GLPixelBuffer")
}; };

View File

@ -1,3 +1,5 @@
/* SPDX-License-Identifier: Apache-2.0 */
#include "testing/testing.h" #include "testing/testing.h"
#include "GPU_framebuffer.h" #include "GPU_framebuffer.h"

View File

@ -26,29 +26,53 @@
namespace blender::gpu { namespace blender::gpu {
void VKBackend::init_platform() static eGPUOSType determine_os_type()
{ {
BLI_assert(!GPG.initialized); #ifdef _WIN32
return GPU_OS_WIN;
#elif defined(__APPLE__)
return GPU_OS_MAC;
#else
return GPU_OS_UNIX;
#endif
}
eGPUDeviceType device = GPU_DEVICE_ANY; void VKBackend::platform_init()
eGPUOSType os = GPU_OS_ANY; {
GPG.init(GPU_DEVICE_ANY,
determine_os_type(),
GPU_DRIVER_ANY,
GPU_SUPPORT_LEVEL_SUPPORTED,
GPU_BACKEND_VULKAN,
"",
"",
"");
}
void VKBackend::platform_init(const VKDevice &device)
{
const VkPhysicalDeviceProperties &properties = device.physical_device_properties_get();
eGPUDeviceType device_type = device.device_type();
eGPUOSType os = determine_os_type();
eGPUDriverType driver = GPU_DRIVER_ANY; eGPUDriverType driver = GPU_DRIVER_ANY;
eGPUSupportLevel support_level = GPU_SUPPORT_LEVEL_SUPPORTED; eGPUSupportLevel support_level = GPU_SUPPORT_LEVEL_SUPPORTED;
#ifdef _WIN32 std::string vendor_name = device.vendor_name();
os = GPU_OS_WIN; std::string driver_version = device.driver_version();
#elif defined(__APPLE__)
os = GPU_OS_MAC;
#else
os = GPU_OS_UNIX;
#endif
GPG.init(device, os, driver, support_level, GPU_BACKEND_VULKAN, "", "", ""); GPG.init(device_type,
os,
driver,
support_level,
GPU_BACKEND_VULKAN,
vendor_name.c_str(),
properties.deviceName,
driver_version.c_str());
} }
void VKBackend::platform_exit() void VKBackend::platform_exit()
{ {
BLI_assert(GPG.initialized);
GPG.clear(); GPG.clear();
} }
@ -147,10 +171,10 @@ shaderc::Compiler &VKBackend::get_shaderc_compiler()
return shaderc_compiler_; return shaderc_compiler_;
} }
void VKBackend::capabilities_init() void VKBackend::capabilities_init(const VKDevice &device)
{ {
const VkPhysicalDeviceLimits &limits = const VkPhysicalDeviceProperties &properties = device.physical_device_properties_get();
VKBackend::get().device_get().physical_device_limits_get(); const VkPhysicalDeviceLimits &limits = properties.limits;
/* Reset all capabilities from previous context. */ /* Reset all capabilities from previous context. */
GCaps = {}; GCaps = {};

View File

@ -36,7 +36,7 @@ class VKBackend : public GPUBackend {
public: public:
VKBackend() VKBackend()
{ {
VKBackend::init_platform(); platform_init();
} }
virtual ~VKBackend() virtual ~VKBackend()
@ -76,8 +76,6 @@ class VKBackend : public GPUBackend {
shaderc::Compiler &get_shaderc_compiler(); shaderc::Compiler &get_shaderc_compiler();
static void capabilities_init();
static VKBackend &get() static VKBackend &get()
{ {
return *static_cast<VKBackend *>(GPUBackend::get()); return *static_cast<VKBackend *>(GPUBackend::get());
@ -88,8 +86,11 @@ class VKBackend : public GPUBackend {
return device_; return device_;
} }
static void platform_init(const VKDevice &device);
static void capabilities_init(const VKDevice &device);
private: private:
static void init_platform(); static void platform_init();
static void platform_exit(); static void platform_exit();
/* These classes are allowed to modify the global device. */ /* These classes are allowed to modify the global device. */

View File

@ -24,7 +24,7 @@ void VKDevice::deinit()
vk_device_ = VK_NULL_HANDLE; vk_device_ = VK_NULL_HANDLE;
vk_queue_family_ = 0; vk_queue_family_ = 0;
vk_queue_ = VK_NULL_HANDLE; vk_queue_ = VK_NULL_HANDLE;
vk_physical_device_limits_ = {}; vk_physical_device_properties_ = {};
} }
bool VKDevice::is_initialized() const bool VKDevice::is_initialized() const
@ -42,8 +42,9 @@ void VKDevice::init(void *ghost_context)
&vk_queue_family_, &vk_queue_family_,
&vk_queue_); &vk_queue_);
init_physical_device_limits(); init_physical_device_properties();
init_capabilities(); VKBackend::platform_init(*this);
VKBackend::capabilities_init(*this);
init_debug_callbacks(); init_debug_callbacks();
init_memory_allocator(); init_memory_allocator();
init_descriptor_pools(); init_descriptor_pools();
@ -57,17 +58,10 @@ void VKDevice::init_debug_callbacks()
debugging_tools_.init(vk_instance_); debugging_tools_.init(vk_instance_);
} }
void VKDevice::init_physical_device_limits() void VKDevice::init_physical_device_properties()
{ {
BLI_assert(vk_physical_device_ != VK_NULL_HANDLE); BLI_assert(vk_physical_device_ != VK_NULL_HANDLE);
VkPhysicalDeviceProperties properties = {}; vkGetPhysicalDeviceProperties(vk_physical_device_, &vk_physical_device_properties_);
vkGetPhysicalDeviceProperties(vk_physical_device_, &properties);
vk_physical_device_limits_ = properties.limits;
}
void VKDevice::init_capabilities()
{
VKBackend::capabilities_init();
} }
void VKDevice::init_memory_allocator() void VKDevice::init_memory_allocator()
@ -87,4 +81,98 @@ void VKDevice::init_descriptor_pools()
descriptor_pools_.init(vk_device_); descriptor_pools_.init(vk_device_);
} }
/* -------------------------------------------------------------------- */
/** \name Platform/driver/device information
* \{ */
constexpr int32_t PCI_ID_NVIDIA = 0x10de;
constexpr int32_t PCI_ID_INTEL = 0x8086;
constexpr int32_t PCI_ID_AMD = 0x1022;
eGPUDeviceType VKDevice::device_type() const
{
/* According to the vulkan specifications:
*
* If the vendor has a PCI vendor ID, the low 16 bits of vendorID must contain that PCI vendor
* ID, and the remaining bits must be set to zero. Otherwise, the value returned must be a valid
* Khronos vendor ID.
*/
switch (vk_physical_device_properties_.vendorID) {
case PCI_ID_NVIDIA:
return GPU_DEVICE_NVIDIA;
case PCI_ID_INTEL:
return GPU_DEVICE_INTEL;
case PCI_ID_AMD:
return GPU_DEVICE_ATI;
default:
break;
}
return GPU_DEVICE_UNKNOWN;
}
eGPUDriverType VKDevice::driver_type() const
{
/* It is unclear how to determine the driver type, but it is required to extract the correct
* driver version. */
return GPU_DRIVER_ANY;
}
std::string VKDevice::vendor_name() const
{
/* Below 0x10000 are the PCI vendor IDs (https://pcisig.com/membership/member-companies) */
if (vk_physical_device_properties_.vendorID < 0x10000) {
switch (vk_physical_device_properties_.vendorID) {
case 0x1022:
return "Advanced Micro Devices";
case 0x10DE:
return "NVIDIA Corporation";
case 0x8086:
return "Intel Corporation";
default:
return std::to_string(vk_physical_device_properties_.vendorID);
}
}
else {
/* above 0x10000 should be vkVendorIDs
* NOTE: When debug_messaging landed we can use something similar to
* vk::to_string(vk::VendorId(properties.vendorID));
*/
return std::to_string(vk_physical_device_properties_.vendorID);
}
}
std::string VKDevice::driver_version() const
{
/*
* NOTE: this depends on the driver type and is currently incorrect. Idea is to use a default per
* OS.
*/
const uint32_t driver_version = vk_physical_device_properties_.driverVersion;
switch (vk_physical_device_properties_.vendorID) {
case PCI_ID_NVIDIA:
return std::to_string((driver_version >> 22) & 0x3FF) + "." +
std::to_string((driver_version >> 14) & 0xFF) + "." +
std::to_string((driver_version >> 6) & 0xFF) + "." +
std::to_string(driver_version & 0x3F);
case PCI_ID_INTEL: {
const uint32_t major = VK_VERSION_MAJOR(driver_version);
/* When using Mesa driver we should use VK_VERSION_*. */
if (major > 30) {
return std::to_string((driver_version >> 14) & 0x3FFFF) + "." +
std::to_string((driver_version & 0x3FFF));
}
break;
}
default:
break;
}
return std::to_string(VK_VERSION_MAJOR(driver_version)) + "." +
std::to_string(VK_VERSION_MINOR(driver_version)) + "." +
std::to_string(VK_VERSION_PATCH(driver_version));
}
/** \} */
} // namespace blender::gpu } // namespace blender::gpu

Some files were not shown because too many files have changed in this diff Show More