Ansariel 2021-11-12 11:02:00 +01:00
commit d06c357bab
134 changed files with 11351 additions and 794 deletions

View File

@ -3476,9 +3476,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>b639d0035f4a8c9b4973be428a1b7e61</string>
<string>5e553a4358203f283c74744aed2fcd8c</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/69569/671323/vlc_bin-3.0.9.549888-darwin64-549888.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54836/510036/vlc_bin-2.2.8.538966-darwin64-538966.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@ -3512,9 +3512,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>4f50b0c47daa081dd4fcb83763d5b0b2</string>
<string>ca84b7c5f86e702fb35727eed8f0c8c4</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/69567/671314/vlc_bin-3.0.9.549888-windows-549888.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54958/511725/vlc_bin-2.2.8.538966-windows-538966.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -3524,16 +3524,16 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>c2f8c01fb6c261b72beb07f0c4cd423f</string>
<string>93cd88d90cb8aedbed5cd90ff9262409</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/69568/671315/vlc_bin-3.0.9.549888-windows64-549888.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54954/511718/vlc_bin-2.2.8.538966-windows64-538966.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
<string>3.0.9.549888</string>
<string>2.2.8.538966</string>
</map>
<key>xmlrpc-epi</key>
<map>

View File

@ -72,7 +72,8 @@ mSystem(system),
mCurrentInternetStreamp(NULL),
mStreamGroup(NULL),
mFMODInternetStreamChannelp(NULL),
mGain(1.0f)
mGain(1.0f),
mWasAlreadyPlaying(false)
{
// Number of milliseconds of audio to buffer for the audio card.
// Must be larger than the usual Second Life frame stutter time.
@ -158,18 +159,14 @@ void LLStreamingAudio_FMODSTUDIO::update()
if (Check_FMOD_Error(mCurrentInternetStreamp->getOpenState(open_state, &progress, &starving, &diskbusy), "FMOD::Sound::getOpenState"))
{
LL_WARNS() << "Internet stream openstate error: open_state = " << open_state << " - progress = " << progress << " - starving = " << starving << " - diskbusy = " << diskbusy << LL_ENDL;
bool was_playing = mWasAlreadyPlaying;
stop();
return;
}
else if (open_state == FMOD_OPENSTATE_ERROR)
{
// Actually we might not get into this case at all since according to the
// FMOD API doc, one should check the result of getOpenState for further
// details, which most likely means if open_state is FMOD_OPENSTATE_ERROR,
// calling getOpenState will return anything but FMOD_OK and we end up in
// the if-case above.
LL_WARNS() << "Internet stream openstate error: progress = " << progress << " - starving = " << starving << " - diskbusy = " << diskbusy << LL_ENDL;
stop();
// Try to restart previously playing stream on socket error
if (open_state == FMOD_OPENSTATE_ERROR && was_playing)
{
LL_WARNS() << "Stream was playing before - trying to restart" << LL_ENDL;
start(mURL);
}
return;
}
else if (open_state == FMOD_OPENSTATE_READY)
@ -183,6 +180,14 @@ void LLStreamingAudio_FMODSTUDIO::update()
// Reset volume to previously set volume
setGain(getGain());
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
mWasAlreadyPlaying = true;
}
}
else if (open_state == FMOD_OPENSTATE_PLAYING)
{
if (!mWasAlreadyPlaying)
{
mWasAlreadyPlaying = true;
}
}
@ -317,6 +322,7 @@ void LLStreamingAudio_FMODSTUDIO::update()
void LLStreamingAudio_FMODSTUDIO::stop()
{
mPendingURL.clear();
mWasAlreadyPlaying = false;
if (mFMODInternetStreamChannelp)
{

View File

@ -80,6 +80,8 @@ private:
bool mNewMetadata;
LLSD mMetadata;
// </DKO> Streamtitle display
bool mWasAlreadyPlaying;
};

View File

@ -0,0 +1,582 @@
// Provides an efficient blocking version of moodycamel::ConcurrentQueue.
// ©2015-2020 Cameron Desrochers. Distributed under the terms of the simplified
// BSD license, available at the top of concurrentqueue.h.
// Also dual-licensed under the Boost Software License (see LICENSE.md)
// Uses Jeff Preshing's semaphore implementation (under the terms of its
// separate zlib license, see lightweightsemaphore.h).
#pragma once
#include "concurrentqueue.h"
#include "lightweightsemaphore.h"
#include <type_traits>
#include <cerrno>
#include <memory>
#include <chrono>
#include <ctime>
namespace moodycamel
{
// This is a blocking version of the queue. It has an almost identical interface to
// the normal non-blocking version, with the addition of various wait_dequeue() methods
// and the removal of producer-specific dequeue methods.
template<typename T, typename Traits = ConcurrentQueueDefaultTraits>
class BlockingConcurrentQueue
{
private:
typedef ::moodycamel::ConcurrentQueue<T, Traits> ConcurrentQueue;
typedef ::moodycamel::LightweightSemaphore LightweightSemaphore;
public:
typedef typename ConcurrentQueue::producer_token_t producer_token_t;
typedef typename ConcurrentQueue::consumer_token_t consumer_token_t;
typedef typename ConcurrentQueue::index_t index_t;
typedef typename ConcurrentQueue::size_t size_t;
typedef typename std::make_signed<size_t>::type ssize_t;
static const size_t BLOCK_SIZE = ConcurrentQueue::BLOCK_SIZE;
static const size_t EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD = ConcurrentQueue::EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD;
static const size_t EXPLICIT_INITIAL_INDEX_SIZE = ConcurrentQueue::EXPLICIT_INITIAL_INDEX_SIZE;
static const size_t IMPLICIT_INITIAL_INDEX_SIZE = ConcurrentQueue::IMPLICIT_INITIAL_INDEX_SIZE;
static const size_t INITIAL_IMPLICIT_PRODUCER_HASH_SIZE = ConcurrentQueue::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE;
static const std::uint32_t EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE = ConcurrentQueue::EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE;
static const size_t MAX_SUBQUEUE_SIZE = ConcurrentQueue::MAX_SUBQUEUE_SIZE;
public:
// Creates a queue with at least `capacity` element slots; note that the
// actual number of elements that can be inserted without additional memory
// allocation depends on the number of producers and the block size (e.g. if
// the block size is equal to `capacity`, only a single block will be allocated
// up-front, which means only a single producer will be able to enqueue elements
// without an extra allocation -- blocks aren't shared between producers).
// This method is not thread safe -- it is up to the user to ensure that the
// queue is fully constructed before it starts being used by other threads (this
// includes making the memory effects of construction visible, possibly with a
// memory barrier).
explicit BlockingConcurrentQueue(size_t capacity = 6 * BLOCK_SIZE)
: inner(capacity), sema(create<LightweightSemaphore, ssize_t, int>(0, (int)Traits::MAX_SEMA_SPINS), &BlockingConcurrentQueue::template destroy<LightweightSemaphore>)
{
assert(reinterpret_cast<ConcurrentQueue*>((BlockingConcurrentQueue*)1) == &((BlockingConcurrentQueue*)1)->inner && "BlockingConcurrentQueue must have ConcurrentQueue as its first member");
if (!sema) {
MOODYCAMEL_THROW(std::bad_alloc());
}
}
BlockingConcurrentQueue(size_t minCapacity, size_t maxExplicitProducers, size_t maxImplicitProducers)
: inner(minCapacity, maxExplicitProducers, maxImplicitProducers), sema(create<LightweightSemaphore, ssize_t, int>(0, (int)Traits::MAX_SEMA_SPINS), &BlockingConcurrentQueue::template destroy<LightweightSemaphore>)
{
assert(reinterpret_cast<ConcurrentQueue*>((BlockingConcurrentQueue*)1) == &((BlockingConcurrentQueue*)1)->inner && "BlockingConcurrentQueue must have ConcurrentQueue as its first member");
if (!sema) {
MOODYCAMEL_THROW(std::bad_alloc());
}
}
// Disable copying and copy assignment
BlockingConcurrentQueue(BlockingConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION;
BlockingConcurrentQueue& operator=(BlockingConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION;
// Moving is supported, but note that it is *not* a thread-safe operation.
// Nobody can use the queue while it's being moved, and the memory effects
// of that move must be propagated to other threads before they can use it.
// Note: When a queue is moved, its tokens are still valid but can only be
// used with the destination queue (i.e. semantically they are moved along
// with the queue itself).
BlockingConcurrentQueue(BlockingConcurrentQueue&& other) MOODYCAMEL_NOEXCEPT
: inner(std::move(other.inner)), sema(std::move(other.sema))
{ }
inline BlockingConcurrentQueue& operator=(BlockingConcurrentQueue&& other) MOODYCAMEL_NOEXCEPT
{
return swap_internal(other);
}
// Swaps this queue's state with the other's. Not thread-safe.
// Swapping two queues does not invalidate their tokens, however
// the tokens that were created for one queue must be used with
// only the swapped queue (i.e. the tokens are tied to the
// queue's movable state, not the object itself).
inline void swap(BlockingConcurrentQueue& other) MOODYCAMEL_NOEXCEPT
{
swap_internal(other);
}
private:
BlockingConcurrentQueue& swap_internal(BlockingConcurrentQueue& other)
{
if (this == &other) {
return *this;
}
inner.swap(other.inner);
sema.swap(other.sema);
return *this;
}
public:
// Enqueues a single item (by copying it).
// Allocates memory if required. Only fails if memory allocation fails (or implicit
// production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0,
// or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
// Thread-safe.
inline bool enqueue(T const& item)
{
if ((details::likely)(inner.enqueue(item))) {
sema->signal();
return true;
}
return false;
}
// Enqueues a single item (by moving it, if possible).
// Allocates memory if required. Only fails if memory allocation fails (or implicit
// production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0,
// or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
// Thread-safe.
inline bool enqueue(T&& item)
{
if ((details::likely)(inner.enqueue(std::move(item)))) {
sema->signal();
return true;
}
return false;
}
// Enqueues a single item (by copying it) using an explicit producer token.
// Allocates memory if required. Only fails if memory allocation fails (or
// Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
// Thread-safe.
inline bool enqueue(producer_token_t const& token, T const& item)
{
if ((details::likely)(inner.enqueue(token, item))) {
sema->signal();
return true;
}
return false;
}
// Enqueues a single item (by moving it, if possible) using an explicit producer token.
// Allocates memory if required. Only fails if memory allocation fails (or
// Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
// Thread-safe.
inline bool enqueue(producer_token_t const& token, T&& item)
{
if ((details::likely)(inner.enqueue(token, std::move(item)))) {
sema->signal();
return true;
}
return false;
}
// Enqueues several items.
// Allocates memory if required. Only fails if memory allocation fails (or
// implicit production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE
// is 0, or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
// Note: Use std::make_move_iterator if the elements should be moved instead of copied.
// Thread-safe.
template<typename It>
inline bool enqueue_bulk(It itemFirst, size_t count)
{
if ((details::likely)(inner.enqueue_bulk(std::forward<It>(itemFirst), count))) {
sema->signal((LightweightSemaphore::ssize_t)(ssize_t)count);
return true;
}
return false;
}
// Enqueues several items using an explicit producer token.
// Allocates memory if required. Only fails if memory allocation fails
// (or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
// Note: Use std::make_move_iterator if the elements should be moved
// instead of copied.
// Thread-safe.
template<typename It>
inline bool enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count)
{
if ((details::likely)(inner.enqueue_bulk(token, std::forward<It>(itemFirst), count))) {
sema->signal((LightweightSemaphore::ssize_t)(ssize_t)count);
return true;
}
return false;
}
// Enqueues a single item (by copying it).
// Does not allocate memory. Fails if not enough room to enqueue (or implicit
// production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE
// is 0).
// Thread-safe.
inline bool try_enqueue(T const& item)
{
if (inner.try_enqueue(item)) {
sema->signal();
return true;
}
return false;
}
// Enqueues a single item (by moving it, if possible).
// Does not allocate memory (except for one-time implicit producer).
// Fails if not enough room to enqueue (or implicit production is
// disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0).
// Thread-safe.
inline bool try_enqueue(T&& item)
{
if (inner.try_enqueue(std::move(item))) {
sema->signal();
return true;
}
return false;
}
// Enqueues a single item (by copying it) using an explicit producer token.
// Does not allocate memory. Fails if not enough room to enqueue.
// Thread-safe.
inline bool try_enqueue(producer_token_t const& token, T const& item)
{
if (inner.try_enqueue(token, item)) {
sema->signal();
return true;
}
return false;
}
// Enqueues a single item (by moving it, if possible) using an explicit producer token.
// Does not allocate memory. Fails if not enough room to enqueue.
// Thread-safe.
inline bool try_enqueue(producer_token_t const& token, T&& item)
{
if (inner.try_enqueue(token, std::move(item))) {
sema->signal();
return true;
}
return false;
}
// Enqueues several items.
// Does not allocate memory (except for one-time implicit producer).
// Fails if not enough room to enqueue (or implicit production is
// disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0).
// Note: Use std::make_move_iterator if the elements should be moved
// instead of copied.
// Thread-safe.
template<typename It>
inline bool try_enqueue_bulk(It itemFirst, size_t count)
{
if (inner.try_enqueue_bulk(std::forward<It>(itemFirst), count)) {
sema->signal((LightweightSemaphore::ssize_t)(ssize_t)count);
return true;
}
return false;
}
// Enqueues several items using an explicit producer token.
// Does not allocate memory. Fails if not enough room to enqueue.
// Note: Use std::make_move_iterator if the elements should be moved
// instead of copied.
// Thread-safe.
template<typename It>
inline bool try_enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count)
{
if (inner.try_enqueue_bulk(token, std::forward<It>(itemFirst), count)) {
sema->signal((LightweightSemaphore::ssize_t)(ssize_t)count);
return true;
}
return false;
}
// Attempts to dequeue from the queue.
// Returns false if all producer streams appeared empty at the time they
// were checked (so, the queue is likely but not guaranteed to be empty).
// Never allocates. Thread-safe.
template<typename U>
inline bool try_dequeue(U& item)
{
if (sema->tryWait()) {
while (!inner.try_dequeue(item)) {
continue;
}
return true;
}
return false;
}
// Attempts to dequeue from the queue using an explicit consumer token.
// Returns false if all producer streams appeared empty at the time they
// were checked (so, the queue is likely but not guaranteed to be empty).
// Never allocates. Thread-safe.
template<typename U>
inline bool try_dequeue(consumer_token_t& token, U& item)
{
if (sema->tryWait()) {
while (!inner.try_dequeue(token, item)) {
continue;
}
return true;
}
return false;
}
// Attempts to dequeue several elements from the queue.
// Returns the number of items actually dequeued.
// Returns 0 if all producer streams appeared empty at the time they
// were checked (so, the queue is likely but not guaranteed to be empty).
// Never allocates. Thread-safe.
template<typename It>
inline size_t try_dequeue_bulk(It itemFirst, size_t max)
{
size_t count = 0;
max = (size_t)sema->tryWaitMany((LightweightSemaphore::ssize_t)(ssize_t)max);
while (count != max) {
count += inner.template try_dequeue_bulk<It&>(itemFirst, max - count);
}
return count;
}
// Attempts to dequeue several elements from the queue using an explicit consumer token.
// Returns the number of items actually dequeued.
// Returns 0 if all producer streams appeared empty at the time they
// were checked (so, the queue is likely but not guaranteed to be empty).
// Never allocates. Thread-safe.
template<typename It>
inline size_t try_dequeue_bulk(consumer_token_t& token, It itemFirst, size_t max)
{
size_t count = 0;
max = (size_t)sema->tryWaitMany((LightweightSemaphore::ssize_t)(ssize_t)max);
while (count != max) {
count += inner.template try_dequeue_bulk<It&>(token, itemFirst, max - count);
}
return count;
}
// Blocks the current thread until there's something to dequeue, then
// dequeues it.
// Never allocates. Thread-safe.
template<typename U>
inline void wait_dequeue(U& item)
{
while (!sema->wait()) {
continue;
}
while (!inner.try_dequeue(item)) {
continue;
}
}
// Blocks the current thread until either there's something to dequeue
// or the timeout (specified in microseconds) expires. Returns false
// without setting `item` if the timeout expires, otherwise assigns
// to `item` and returns true.
// Using a negative timeout indicates an indefinite timeout,
// and is thus functionally equivalent to calling wait_dequeue.
// Never allocates. Thread-safe.
template<typename U>
inline bool wait_dequeue_timed(U& item, std::int64_t timeout_usecs)
{
if (!sema->wait(timeout_usecs)) {
return false;
}
while (!inner.try_dequeue(item)) {
continue;
}
return true;
}
// Blocks the current thread until either there's something to dequeue
// or the timeout expires. Returns false without setting `item` if the
// timeout expires, otherwise assigns to `item` and returns true.
// Never allocates. Thread-safe.
template<typename U, typename Rep, typename Period>
inline bool wait_dequeue_timed(U& item, std::chrono::duration<Rep, Period> const& timeout)
{
return wait_dequeue_timed(item, std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());
}
// Blocks the current thread until there's something to dequeue, then
// dequeues it using an explicit consumer token.
// Never allocates. Thread-safe.
template<typename U>
inline void wait_dequeue(consumer_token_t& token, U& item)
{
while (!sema->wait()) {
continue;
}
while (!inner.try_dequeue(token, item)) {
continue;
}
}
// Blocks the current thread until either there's something to dequeue
// or the timeout (specified in microseconds) expires. Returns false
// without setting `item` if the timeout expires, otherwise assigns
// to `item` and returns true.
// Using a negative timeout indicates an indefinite timeout,
// and is thus functionally equivalent to calling wait_dequeue.
// Never allocates. Thread-safe.
template<typename U>
inline bool wait_dequeue_timed(consumer_token_t& token, U& item, std::int64_t timeout_usecs)
{
if (!sema->wait(timeout_usecs)) {
return false;
}
while (!inner.try_dequeue(token, item)) {
continue;
}
return true;
}
// Blocks the current thread until either there's something to dequeue
// or the timeout expires. Returns false without setting `item` if the
// timeout expires, otherwise assigns to `item` and returns true.
// Never allocates. Thread-safe.
template<typename U, typename Rep, typename Period>
inline bool wait_dequeue_timed(consumer_token_t& token, U& item, std::chrono::duration<Rep, Period> const& timeout)
{
return wait_dequeue_timed(token, item, std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());
}
// Attempts to dequeue several elements from the queue.
// Returns the number of items actually dequeued, which will
// always be at least one (this method blocks until the queue
// is non-empty) and at most max.
// Never allocates. Thread-safe.
template<typename It>
inline size_t wait_dequeue_bulk(It itemFirst, size_t max)
{
size_t count = 0;
max = (size_t)sema->waitMany((LightweightSemaphore::ssize_t)(ssize_t)max);
while (count != max) {
count += inner.template try_dequeue_bulk<It&>(itemFirst, max - count);
}
return count;
}
// Attempts to dequeue several elements from the queue.
// Returns the number of items actually dequeued, which can
// be 0 if the timeout expires while waiting for elements,
// and at most max.
// Using a negative timeout indicates an indefinite timeout,
// and is thus functionally equivalent to calling wait_dequeue_bulk.
// Never allocates. Thread-safe.
template<typename It>
inline size_t wait_dequeue_bulk_timed(It itemFirst, size_t max, std::int64_t timeout_usecs)
{
size_t count = 0;
max = (size_t)sema->waitMany((LightweightSemaphore::ssize_t)(ssize_t)max, timeout_usecs);
while (count != max) {
count += inner.template try_dequeue_bulk<It&>(itemFirst, max - count);
}
return count;
}
// Attempts to dequeue several elements from the queue.
// Returns the number of items actually dequeued, which can
// be 0 if the timeout expires while waiting for elements,
// and at most max.
// Never allocates. Thread-safe.
template<typename It, typename Rep, typename Period>
inline size_t wait_dequeue_bulk_timed(It itemFirst, size_t max, std::chrono::duration<Rep, Period> const& timeout)
{
return wait_dequeue_bulk_timed<It&>(itemFirst, max, std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());
}
// Attempts to dequeue several elements from the queue using an explicit consumer token.
// Returns the number of items actually dequeued, which will
// always be at least one (this method blocks until the queue
// is non-empty) and at most max.
// Never allocates. Thread-safe.
template<typename It>
inline size_t wait_dequeue_bulk(consumer_token_t& token, It itemFirst, size_t max)
{
size_t count = 0;
max = (size_t)sema->waitMany((LightweightSemaphore::ssize_t)(ssize_t)max);
while (count != max) {
count += inner.template try_dequeue_bulk<It&>(token, itemFirst, max - count);
}
return count;
}
// Attempts to dequeue several elements from the queue using an explicit consumer token.
// Returns the number of items actually dequeued, which can
// be 0 if the timeout expires while waiting for elements,
// and at most max.
// Using a negative timeout indicates an indefinite timeout,
// and is thus functionally equivalent to calling wait_dequeue_bulk.
// Never allocates. Thread-safe.
template<typename It>
inline size_t wait_dequeue_bulk_timed(consumer_token_t& token, It itemFirst, size_t max, std::int64_t timeout_usecs)
{
size_t count = 0;
max = (size_t)sema->waitMany((LightweightSemaphore::ssize_t)(ssize_t)max, timeout_usecs);
while (count != max) {
count += inner.template try_dequeue_bulk<It&>(token, itemFirst, max - count);
}
return count;
}
// Attempts to dequeue several elements from the queue using an explicit consumer token.
// Returns the number of items actually dequeued, which can
// be 0 if the timeout expires while waiting for elements,
// and at most max.
// Never allocates. Thread-safe.
template<typename It, typename Rep, typename Period>
inline size_t wait_dequeue_bulk_timed(consumer_token_t& token, It itemFirst, size_t max, std::chrono::duration<Rep, Period> const& timeout)
{
return wait_dequeue_bulk_timed<It&>(token, itemFirst, max, std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());
}
// Returns an estimate of the total number of elements currently in the queue. This
// estimate is only accurate if the queue has completely stabilized before it is called
// (i.e. all enqueue and dequeue operations have completed and their memory effects are
// visible on the calling thread, and no further operations start while this method is
// being called).
// Thread-safe.
inline size_t size_approx() const
{
return (size_t)sema->availableApprox();
}
// Returns true if the underlying atomic variables used by
// the queue are lock-free (they should be on most platforms).
// Thread-safe.
static bool is_lock_free()
{
return ConcurrentQueue::is_lock_free();
}
private:
template<typename U, typename A1, typename A2>
static inline U* create(A1&& a1, A2&& a2)
{
void* p = (Traits::malloc)(sizeof(U));
return p != nullptr ? new (p) U(std::forward<A1>(a1), std::forward<A2>(a2)) : nullptr;
}
template<typename U>
static inline void destroy(U* p)
{
if (p != nullptr) {
p->~U();
}
(Traits::free)(p);
}
private:
ConcurrentQueue inner;
std::unique_ptr<LightweightSemaphore, void (*)(LightweightSemaphore*)> sema;
};
template<typename T, typename Traits>
inline void swap(BlockingConcurrentQueue<T, Traits>& a, BlockingConcurrentQueue<T, Traits>& b) MOODYCAMEL_NOEXCEPT
{
a.swap(b);
}
} // end namespace moodycamel

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,411 @@
// Provides an efficient implementation of a semaphore (LightweightSemaphore).
// This is an extension of Jeff Preshing's sempahore implementation (licensed
// under the terms of its separate zlib license) that has been adapted and
// extended by Cameron Desrochers.
#pragma once
#include <cstddef> // For std::size_t
#include <atomic>
#include <type_traits> // For std::make_signed<T>
#if defined(_WIN32)
// Avoid including windows.h in a header; we only need a handful of
// items, so we'll redeclare them here (this is relatively safe since
// the API generally has to remain stable between Windows versions).
// I know this is an ugly hack but it still beats polluting the global
// namespace with thousands of generic names or adding a .cpp for nothing.
extern "C" {
struct _SECURITY_ATTRIBUTES;
__declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES* lpSemaphoreAttributes, long lInitialCount, long lMaximumCount, const wchar_t* lpName);
__declspec(dllimport) int __stdcall CloseHandle(void* hObject);
__declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void* hHandle, unsigned long dwMilliseconds);
__declspec(dllimport) int __stdcall ReleaseSemaphore(void* hSemaphore, long lReleaseCount, long* lpPreviousCount);
}
#elif defined(__MACH__)
#include <mach/mach.h>
#elif defined(__unix__)
#include <semaphore.h>
#endif
namespace moodycamel
{
namespace details
{
// Code in the mpmc_sema namespace below is an adaptation of Jeff Preshing's
// portable + lightweight semaphore implementations, originally from
// https://github.com/preshing/cpp11-on-multicore/blob/master/common/sema.h
// LICENSE:
// Copyright (c) 2015 Jeff Preshing
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgement in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
#if defined(_WIN32)
class Semaphore
{
private:
void* m_hSema;
Semaphore(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
Semaphore& operator=(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
public:
Semaphore(int initialCount = 0)
{
assert(initialCount >= 0);
const long maxLong = 0x7fffffff;
m_hSema = CreateSemaphoreW(nullptr, initialCount, maxLong, nullptr);
assert(m_hSema);
}
~Semaphore()
{
CloseHandle(m_hSema);
}
bool wait()
{
const unsigned long infinite = 0xffffffff;
return WaitForSingleObject(m_hSema, infinite) == 0;
}
bool try_wait()
{
return WaitForSingleObject(m_hSema, 0) == 0;
}
bool timed_wait(std::uint64_t usecs)
{
return WaitForSingleObject(m_hSema, (unsigned long)(usecs / 1000)) == 0;
}
void signal(int count = 1)
{
while (!ReleaseSemaphore(m_hSema, count, nullptr));
}
};
#elif defined(__MACH__)
//---------------------------------------------------------
// Semaphore (Apple iOS and OSX)
// Can't use POSIX semaphores due to http://lists.apple.com/archives/darwin-kernel/2009/Apr/msg00010.html
//---------------------------------------------------------
class Semaphore
{
private:
semaphore_t m_sema;
Semaphore(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
Semaphore& operator=(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
public:
Semaphore(int initialCount = 0)
{
assert(initialCount >= 0);
kern_return_t rc = semaphore_create(mach_task_self(), &m_sema, SYNC_POLICY_FIFO, initialCount);
assert(rc == KERN_SUCCESS);
(void)rc;
}
~Semaphore()
{
semaphore_destroy(mach_task_self(), m_sema);
}
bool wait()
{
return semaphore_wait(m_sema) == KERN_SUCCESS;
}
bool try_wait()
{
return timed_wait(0);
}
bool timed_wait(std::uint64_t timeout_usecs)
{
mach_timespec_t ts;
ts.tv_sec = static_cast<unsigned int>(timeout_usecs / 1000000);
ts.tv_nsec = static_cast<int>((timeout_usecs % 1000000) * 1000);
// added in OSX 10.10: https://developer.apple.com/library/prerelease/mac/documentation/General/Reference/APIDiffsMacOSX10_10SeedDiff/modules/Darwin.html
kern_return_t rc = semaphore_timedwait(m_sema, ts);
return rc == KERN_SUCCESS;
}
void signal()
{
while (semaphore_signal(m_sema) != KERN_SUCCESS);
}
void signal(int count)
{
while (count-- > 0)
{
while (semaphore_signal(m_sema) != KERN_SUCCESS);
}
}
};
#elif defined(__unix__)
//---------------------------------------------------------
// Semaphore (POSIX, Linux)
//---------------------------------------------------------
class Semaphore
{
private:
sem_t m_sema;
Semaphore(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
Semaphore& operator=(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
public:
Semaphore(int initialCount = 0)
{
assert(initialCount >= 0);
int rc = sem_init(&m_sema, 0, static_cast<unsigned int>(initialCount));
assert(rc == 0);
(void)rc;
}
~Semaphore()
{
sem_destroy(&m_sema);
}
bool wait()
{
// http://stackoverflow.com/questions/2013181/gdb-causes-sem-wait-to-fail-with-eintr-error
int rc;
do {
rc = sem_wait(&m_sema);
} while (rc == -1 && errno == EINTR);
return rc == 0;
}
bool try_wait()
{
int rc;
do {
rc = sem_trywait(&m_sema);
} while (rc == -1 && errno == EINTR);
return rc == 0;
}
bool timed_wait(std::uint64_t usecs)
{
struct timespec ts;
const int usecs_in_1_sec = 1000000;
const int nsecs_in_1_sec = 1000000000;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += (time_t)(usecs / usecs_in_1_sec);
ts.tv_nsec += (long)(usecs % usecs_in_1_sec) * 1000;
// sem_timedwait bombs if you have more than 1e9 in tv_nsec
// so we have to clean things up before passing it in
if (ts.tv_nsec >= nsecs_in_1_sec) {
ts.tv_nsec -= nsecs_in_1_sec;
++ts.tv_sec;
}
int rc;
do {
rc = sem_timedwait(&m_sema, &ts);
} while (rc == -1 && errno == EINTR);
return rc == 0;
}
void signal()
{
while (sem_post(&m_sema) == -1);
}
void signal(int count)
{
while (count-- > 0)
{
while (sem_post(&m_sema) == -1);
}
}
};
#else
#error Unsupported platform! (No semaphore wrapper available)
#endif
} // end namespace details
//---------------------------------------------------------
// LightweightSemaphore
//---------------------------------------------------------
class LightweightSemaphore
{
public:
typedef std::make_signed<std::size_t>::type ssize_t;
private:
std::atomic<ssize_t> m_count;
details::Semaphore m_sema;
int m_maxSpins;
bool waitWithPartialSpinning(std::int64_t timeout_usecs = -1)
{
ssize_t oldCount;
int spin = m_maxSpins;
while (--spin >= 0)
{
oldCount = m_count.load(std::memory_order_relaxed);
if ((oldCount > 0) && m_count.compare_exchange_strong(oldCount, oldCount - 1, std::memory_order_acquire, std::memory_order_relaxed))
return true;
std::atomic_signal_fence(std::memory_order_acquire); // Prevent the compiler from collapsing the loop.
}
oldCount = m_count.fetch_sub(1, std::memory_order_acquire);
if (oldCount > 0)
return true;
if (timeout_usecs < 0)
{
if (m_sema.wait())
return true;
}
if (timeout_usecs > 0 && m_sema.timed_wait((std::uint64_t)timeout_usecs))
return true;
// At this point, we've timed out waiting for the semaphore, but the
// count is still decremented indicating we may still be waiting on
// it. So we have to re-adjust the count, but only if the semaphore
// wasn't signaled enough times for us too since then. If it was, we
// need to release the semaphore too.
while (true)
{
oldCount = m_count.load(std::memory_order_acquire);
if (oldCount >= 0 && m_sema.try_wait())
return true;
if (oldCount < 0 && m_count.compare_exchange_strong(oldCount, oldCount + 1, std::memory_order_relaxed, std::memory_order_relaxed))
return false;
}
}
ssize_t waitManyWithPartialSpinning(ssize_t max, std::int64_t timeout_usecs = -1)
{
assert(max > 0);
ssize_t oldCount;
int spin = m_maxSpins;
while (--spin >= 0)
{
oldCount = m_count.load(std::memory_order_relaxed);
if (oldCount > 0)
{
ssize_t newCount = oldCount > max ? oldCount - max : 0;
if (m_count.compare_exchange_strong(oldCount, newCount, std::memory_order_acquire, std::memory_order_relaxed))
return oldCount - newCount;
}
std::atomic_signal_fence(std::memory_order_acquire);
}
oldCount = m_count.fetch_sub(1, std::memory_order_acquire);
if (oldCount <= 0)
{
if ((timeout_usecs == 0) || (timeout_usecs < 0 && !m_sema.wait()) || (timeout_usecs > 0 && !m_sema.timed_wait((std::uint64_t)timeout_usecs)))
{
while (true)
{
oldCount = m_count.load(std::memory_order_acquire);
if (oldCount >= 0 && m_sema.try_wait())
break;
if (oldCount < 0 && m_count.compare_exchange_strong(oldCount, oldCount + 1, std::memory_order_relaxed, std::memory_order_relaxed))
return 0;
}
}
}
if (max > 1)
return 1 + tryWaitMany(max - 1);
return 1;
}
public:
LightweightSemaphore(ssize_t initialCount = 0, int maxSpins = 10000) : m_count(initialCount), m_maxSpins(maxSpins)
{
assert(initialCount >= 0);
assert(maxSpins >= 0);
}
bool tryWait()
{
ssize_t oldCount = m_count.load(std::memory_order_relaxed);
while (oldCount > 0)
{
if (m_count.compare_exchange_weak(oldCount, oldCount - 1, std::memory_order_acquire, std::memory_order_relaxed))
return true;
}
return false;
}
bool wait()
{
return tryWait() || waitWithPartialSpinning();
}
bool wait(std::int64_t timeout_usecs)
{
return tryWait() || waitWithPartialSpinning(timeout_usecs);
}
// Acquires between 0 and (greedily) max, inclusive
ssize_t tryWaitMany(ssize_t max)
{
assert(max >= 0);
ssize_t oldCount = m_count.load(std::memory_order_relaxed);
while (oldCount > 0)
{
ssize_t newCount = oldCount > max ? oldCount - max : 0;
if (m_count.compare_exchange_weak(oldCount, newCount, std::memory_order_acquire, std::memory_order_relaxed))
return oldCount - newCount;
}
return 0;
}
// Acquires at least one, and (greedily) at most max
ssize_t waitMany(ssize_t max, std::int64_t timeout_usecs)
{
assert(max >= 0);
ssize_t result = tryWaitMany(max);
if (result == 0 && max > 0)
result = waitManyWithPartialSpinning(max, timeout_usecs);
return result;
}
ssize_t waitMany(ssize_t max)
{
ssize_t result = waitMany(max, -1);
assert(result > 0);
return result;
}
void signal(ssize_t count = 1)
{
assert(count >= 0);
ssize_t oldCount = m_count.fetch_add(count, std::memory_order_release);
ssize_t toRelease = -oldCount < count ? -oldCount : count;
if (toRelease > 0)
{
m_sema.signal((int)toRelease);
}
}
std::size_t availableApprox() const
{
ssize_t count = m_count.load(std::memory_order_relaxed);
return count > 0 ? static_cast<std::size_t>(count) : 0;
}
};
} // end namespace moodycamel

View File

@ -28,4 +28,5 @@
namespace LLProfiler
{
bool active{false};
}

View File

@ -580,6 +580,31 @@ namespace LLTrace
return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
}
template <typename T>
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMedianPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX)
{
num_periods = llmin(num_periods, getNumRecordedPeriods());
std::vector <typename RelatedTypes<typename T::value_t>::fractional_t> buf;
for (S32 i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
if (recording.getDuration() > (F32Seconds)0.f)
{
buf.push_back(recording.getPerSec(stat));
}
}
std::sort(buf.begin(), buf.end());
return typename RelatedTypes<T>::fractional_t((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]);
}
template<typename T>
typename RelatedTypes<T>::fractional_t getPeriodMedianPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
{
return typename RelatedTypes<T>::fractional_t(getPeriodMedianPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
}
//
// PERIODIC STANDARD DEVIATION
//

View File

@ -44,7 +44,7 @@
#include "lltimer.h"
#include "llthread.h"
#include "llmutex.h"
#include "llprofiler.h"
const LLUUID LLUUID::null;
const LLTransactionID LLTransactionID::tnull;
@ -155,6 +155,7 @@ U32 janky_fast_random_seeded_bytes(U32 seed, U32 val)
// Common to all UUID implementations
void LLUUID::toString(std::string& out) const
{
LL_PROFILE_ZONE_SCOPED;
out = llformat(
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
(U8)(mData[0]),
@ -217,6 +218,7 @@ BOOL LLUUID::set(const char* in_string, BOOL emit)
BOOL LLUUID::set(const std::string& in_string, BOOL emit)
{
LL_PROFILE_ZONE_SCOPED;
BOOL broken_format = FALSE;
// empty strings should make NULL uuid
@ -1027,6 +1029,7 @@ LLUUID::LLUUID()
// Copy constructor
LLUUID::LLUUID(const LLUUID& rhs)
{
LL_PROFILE_ZONE_SCOPED;
// <FS> Fix for misaligned unsigned ints in LLUUID; by Sovereign Engineer / Shyotl Kuhr
//U32 *tmp = (U32 *)mData;
//U32 *rhstmp = (U32 *)rhs.mData;
@ -1045,6 +1048,7 @@ LLUUID::LLUUID()
// Assignment
LLUUID& LLUUID::operator=(const LLUUID& rhs)
{
LL_PROFILE_ZONE_SCOPED;
// <FS> Fix for misaligned unsigned ints in LLUUID; by Sovereign Engineer / Shyotl Kuhr
//// No need to check the case where this==&rhs. The branch is slower than the write.
//U32 *tmp = (U32 *)mData;

View File

@ -29,10 +29,11 @@
#include <iostream>
#include <set>
#include <vector>
#include <cstring> // <FS:Beq> for std::memmove
#include "stdtypes.h"
#include "llpreprocessor.h"
#include <boost/functional/hash.hpp>
#include "llprofiler.h"
class LLMutex;
const S32 UUID_BYTES = 16;
@ -56,7 +57,9 @@ public:
explicit LLUUID(const char *in_string); // Convert from string.
explicit LLUUID(const std::string& in_string); // Convert from string.
LLUUID(const LLUUID &in);
LLUUID(LLUUID&& rhs) noexcept { LL_PROFILE_ZONE_SCOPED; std::memmove(mData, rhs.mData, sizeof(mData));};
LLUUID &operator=(const LLUUID &rhs);
LLUUID &operator=(LLUUID &&rhs) noexcept { LL_PROFILE_ZONE_SCOPED; std::memmove(mData, rhs.mData, sizeof(mData));return *this;};
~LLUUID();
@ -112,6 +115,61 @@ public:
void toString(std::string& out) const;
void toCompressedString(char *out) const; // Does not allocate memory, needs 17 characters (including \0)
void toCompressedString(std::string& out) const;
// last 4 chars for quick ref - Very lightweight, no nul-term added - provide your own, ensure min 4 bytes.
# define hexnybl(N) (N)>9?((N)-10)+'a':(N)+'0'
inline char * toShortString(char *out) const
{
LL_PROFILE_ZONE_SCOPED;
out[0] = hexnybl(mData[14]>>4);
out[1] = hexnybl(mData[14]&15);
out[2] = hexnybl(mData[15]>>4);
out[3] = hexnybl(mData[15]&15);
return out;
}
// full uuid - Much lighterweight than default, no allocation, or nul-term added - provide your own, ensure min 36 bytes.
inline char * toStringFast(char *out) const
{
LL_PROFILE_ZONE_SCOPED;
out[0] = hexnybl(mData[0]>>4);
out[1] = hexnybl(mData[0]&15);
out[2] = hexnybl(mData[1]>>4);
out[3] = hexnybl(mData[1]&15);
out[4] = hexnybl(mData[2]>>4);
out[5] = hexnybl(mData[2]&15);
out[6] = hexnybl(mData[3]>>4);
out[7] = hexnybl(mData[3]&15);
out[8] = '-';
out[9] = hexnybl(mData[4]>>4);
out[10] = hexnybl(mData[4]&15);
out[11] = hexnybl(mData[5]>>4);
out[12] = hexnybl(mData[5]&15);
out[13] = '-';
out[14] = hexnybl(mData[6]>>4);
out[15] = hexnybl(mData[6]&15);
out[16] = hexnybl(mData[7]>>4);
out[17] = hexnybl(mData[7]&15);
out[18] = '-';
out[19] = hexnybl(mData[8]>>4);
out[20] = hexnybl(mData[8]&15);
out[21] = hexnybl(mData[9]>>4);
out[22] = hexnybl(mData[9]&15);
out[23] = '-';
out[24] = hexnybl(mData[10]>>4);
out[25] = hexnybl(mData[10]&15);
out[26] = hexnybl(mData[11]>>4);
out[27] = hexnybl(mData[11]&15);
out[28] = hexnybl(mData[12]>>4);
out[29] = hexnybl(mData[12]&15);
out[30] = hexnybl(mData[13]>>4);
out[31] = hexnybl(mData[13]&15);
out[32] = hexnybl(mData[14]>>4);
out[33] = hexnybl(mData[14]&15);
out[34] = hexnybl(mData[15]>>4);
out[35] = hexnybl(mData[15]&15);
return out;
}
std::string asString() const;
std::string getString() const;

View File

@ -35,6 +35,7 @@
#include "apr.h" // thread-related functions
#include "_refcounted.h"
#include "llprofiler.h"
namespace LLCoreInt
{
@ -54,6 +55,10 @@ private:
void run()
{ // THREAD CONTEXT
// <FS:Beq> - Add threadnames
LL_INFOS("THREAD") << "Started unnamed HTTP thread " << LL_ENDL;
LL_PROFILER_THREAD_BEGIN("HTTP");
// </FS:Beq>
// Take out additional reference for the at_exit handler
addRef();
@ -62,7 +67,10 @@ private:
// run the thread function
mThreadFunc(this);
} // THREAD CONTEXT
// <FS:Beq> - Add threadnames
LL_PROFILER_THREAD_END("HTTP");
// </FS:Beq>
} // THREAD CONTEXT
protected:
virtual ~HttpThread()

View File

@ -54,6 +54,10 @@ LLScrollListCell* LLScrollListCell::create(const LLScrollListCell::Params& cell_
{
cell = new LLScrollListIconText(cell_p);
}
else if (cell_p.type() == "bar")
{
cell = new LLScrollListBar(cell_p);
}
else // default is "text"
{
cell = new LLScrollListText(cell_p);
@ -165,6 +169,74 @@ void LLScrollListIcon::draw(const LLColor4& color, const LLColor4& highlight_col
}
}
//
// LLScrollListBar
//
LLScrollListBar::LLScrollListBar(const LLScrollListCell::Params& p)
: LLScrollListCell(p),
mRatio(0),
mColor(p.color),
mBottom(1),
mLeftPad(1),
mRightPad(1)
{}
LLScrollListBar::~LLScrollListBar()
{
}
/*virtual*/
S32 LLScrollListBar::getHeight() const
{
return LLScrollListCell::getHeight();
}
/*virtual*/
const LLSD LLScrollListBar::getValue() const
{
return LLStringUtil::null;
}
void LLScrollListBar::setValue(const LLSD& value)
{
if (value.has("ratio"))
{
mRatio = value["ratio"].asReal();
}
if (value.has("bottom"))
{
mBottom = value["bottom"].asInteger();
}
if (value.has("left_pad"))
{
mLeftPad = value["left_pad"].asInteger();
}
if (value.has("right_pad"))
{
mRightPad = value["right_pad"].asInteger();
}
}
void LLScrollListBar::setColor(const LLColor4& color)
{
mColor = color;
}
S32 LLScrollListBar::getWidth() const
{
return LLScrollListCell::getWidth();
}
void LLScrollListBar::draw(const LLColor4& color, const LLColor4& highlight_color) const
{
S32 bar_width = getWidth() - mLeftPad - mRightPad;
S32 left = bar_width - bar_width * mRatio;
left = llclamp(left, mLeftPad, getWidth() - mRightPad - 1);
gl_rect_2d(left, mBottom, getWidth() - mRightPad, mBottom - 1, mColor);
}
//
// LLScrollListText
//

View File

@ -33,6 +33,7 @@
#include "lluistring.h"
#include "v4color.h"
#include "llui.h"
#include "llgltexture.h"
class LLCheckBoxCtrl;
class LLSD;
@ -153,6 +154,7 @@ public:
void setText(const LLStringExplicit& text);
void setFontStyle(const U8 font_style);
void setAlignment(LLFontGL::HAlign align) { mFontAlignment = align; }
protected:
LLUIString mText;
@ -192,6 +194,26 @@ private:
LLFontGL::HAlign mAlignment;
};
class LLScrollListBar : public LLScrollListCell
{
public:
LLScrollListBar(const LLScrollListCell::Params& p);
/*virtual*/ ~LLScrollListBar();
/*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const;
/*virtual*/ S32 getWidth() const;
/*virtual*/ S32 getHeight() const;
/*virtual*/ const LLSD getValue() const;
/*virtual*/ void setColor(const LLColor4&);
/*virtual*/ void setValue(const LLSD& value);
private:
LLColor4 mColor;
F32 mRatio;
S32 mBottom;
S32 mRightPad;
S32 mLeftPad;
};
/*
* An interactive cell containing a check box.
*/

View File

@ -399,9 +399,12 @@ set(viewer_SOURCE_FILES
llfloaterpathfindinglinksets.cpp
llfloaterpathfindingobjects.cpp
llfloaterpay.cpp
# llfloaterperformance.cpp <FS:Beq/> replaced with fs version due to large changes and likelihood that LL version will not release.
fsfloaterperformance.cpp
llfloaterperms.cpp
llfloaterpostprocess.cpp
llfloaterpreference.cpp
# llfloaterpreferencesgraphicsadvanced.cpp
llfloaterpreferenceviewadvanced.cpp
llfloaterpreviewtrash.cpp
llfloaterproperties.cpp
@ -1177,9 +1180,12 @@ set(viewer_HEADER_FILES
llfloaterpathfindinglinksets.h
llfloaterpathfindingobjects.h
llfloaterpay.h
# llfloaterperformance.h <FS:Beq/> replaced with fs version due to large changes and likelihood that LL version will not release.
fsfloaterperformance.h
llfloaterperms.h
llfloaterpostprocess.h
llfloaterpreference.h
# llfloaterpreferencesgraphicsadvanced.h
llfloaterpreferenceviewadvanced.h
llfloaterpreviewtrash.h
llfloaterproperties.h
@ -1679,6 +1685,10 @@ configure_file(
list(APPEND viewer_HEADER_FILES ${CMAKE_CURRENT_BINARY_DIR}/fsversionvalues.h)
# </FS:TS>
# <FS:Beq> Performance stast support
list(APPEND viewer_SOURCE_FILES fsperfstats.cpp)
list(APPEND viewer_HEADER_FILES fsperfstats.h)
# </FS:Beq>
source_group("CMake Rules" FILES ViewerInstall.cmake)
#build_data.json creation moved to viewer_manifest.py MAINT-6413

View File

@ -638,4 +638,14 @@
is_running_function="Floater.IsOpen"
is_running_parameters="my_environments"
/>
<command name="performance"
available_in_toybox="true"
icon="Command_Performance_Icon"
label_ref="Command_Performance_Label"
tooltip_ref="Command_Performance_Tooltip"
execute_function="Floater.ToggleOrBringToFront"
execute_parameters="performance"
is_running_function="Floater.IsOpen"
is_running_parameters="performance"
/>
</commands>

View File

@ -8171,7 +8171,7 @@
<key>Comment</key>
<string>Duration in seconds of the login SRV request timeout</string>
<key>Persist</key>
<integer>0</integer>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
@ -25712,6 +25712,39 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key>
<integer>0</integer>
</map>
<key>FSTargetFPS</key>
<map>
<key>Comment</key>
<string>Desired minimum FPS</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>25</integer>
</map>
<key>FSAutoTuneFPS</key>
<map>
<key>Comment</key>
<string>Allow the viewer to adjust your settings to achieve target FPS</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>FSPerfFloaterSmoothingPeriods</key>
<map>
<key>Comment</key>
<string>Number of periods to smooth the stats over</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>50</integer>
</map>
<key>FSAutoUnmuteSounds</key>
<map>
<key>Comment</key>
@ -25734,5 +25767,115 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderJellyDollsAsImpostors</key>
<map>
<key>Comment</key>
<string>Use an impostor instead of a JellyDoll for better visuals (true)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>FSPerfStatsCaptureEnabled</key>
<map>
<key>Comment</key>
<string>Enable/disable render time data to support autotune.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>FSAutoTuneImpostorByDistEnabled</key>
<map>
<key>Comment</key>
<string>Enable/disable using MaxNonImpostor to limit avatar rendering by distance.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>FSAllowSelfImpostor</key>
<map>
<key>Comment</key>
<string>Allow own render time to impostor your avatar.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>FSShowTunedART</key>
<map>
<key>Comment</key>
<string>Show the tuned render time in the avatar display.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>FSRenderAvatarMaxART</key>
<map>
<key>Comment</key>
<string>Render Time Limit in microseconds (0.0 = no limit)</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>4.699</real>
</map>
<key>FSAutoTuneRenderFarClipMin</key>
<map>
<key>Comment</key>
<string>The lowest draw distance that auto tune is allowed to use</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>32.0</real>
</map>
<key>FSAutoTuneRenderFarClipTarget</key>
<map>
<key>Comment</key>
<string>The draw distance that auto tune will try to achieve</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>256.0</real>
</map>
<key>FSAutoTuneImpostorFarAwayDistance</key>
<map>
<key>Comment</key>
<string>Avatars beyond this range will automatically be optimized</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>64.0</real>
</map>
<key>FSTuningFPSStrategy</key>
<map>
<key>Comment</key>
<string>Strategy to use when tuning FPS. 0=Tune avatar rendering only, 1=Tune both avatar and global scene settings.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
</llsd>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
/**
* @file fsfloaterperformance.h
*
* This is forked directly from an early access release of llfloaterperformance.h
*
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2021, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef FS_FLOATERPERFORMANCE_H
#define FS_FLOATERPERFORMANCE_H
#include "llfloater.h"
#include "lllistcontextmenu.h"
class LLCharacter;
class LLNameListCtrl;
class LLComboBox;
class FSFloaterPerformance : public LLFloater
{
public:
FSFloaterPerformance(const LLSD& key);
virtual ~FSFloaterPerformance();
/*virtual*/ BOOL postBuild();
/*virtual*/ void draw();
void showSelectedPanel(LLPanel* selected_panel);
void showMainPanel();
void hidePanels();
void detachItem(const LLUUID& item_id);
void onAvatarListRightClick(LLUICtrl* ctrl, S32 x, S32 y);
void onCustomAction (const LLSD& userdata, const LLUUID& av_id);
bool isActionChecked(const LLSD& userdata, const LLUUID& av_id);
void onExtendedAction(const LLSD& userdata, const LLUUID& av_id);
private:
void initBackBtn(LLPanel* panel);
void populateHUDList();
void populateObjectList();
void populateNearbyList();
void onChangeQuality(const LLSD& data);
void onClickHideAvatars();
void onClickExceptions();
void onClickFocusAvatar();
void updateMaxComplexity();
void updateComplexityText();
void updateMaxRenderTime();
void updateMaxRenderTimeText();
void getNearbyAvatars(std::vector<LLCharacter*> &valid_nearby_avs);
LLPanel* mMainPanel;
LLPanel* mNearbyPanel;
LLPanel* mComplexityPanel;
LLPanel* mHUDsPanel;
LLPanel* mSettingsPanel;
LLPanel* mAutoTunePanel;
LLNameListCtrl* mHUDList;
LLNameListCtrl* mObjectList;
LLNameListCtrl* mNearbyList;
LLComboBox* mNearbyCombo;
LLListContextMenu* mContextMenu;
LLTimer* mUpdateTimer;
S32 mNearbyMaxComplexity;
boost::signals2::connection mComplexityChangedSignal;
boost::signals2::connection mMaxARTChangedSignal;
};
#endif // FS_FLOATERPERFORMANCE_H

View File

@ -0,0 +1,419 @@
/**
* @file fsperfstats.cpp
* @brief Stats collection to support perf floater and auto tune
*
* $LicenseInfo:firstyear=2021&license=fsviewerlgpl$
* Phoenix Firestorm Viewer Source Code
* Copyright (C) 2021, The Phoenix Firestorm Project, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
* http://www.firestormviewer.org
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "fsperfstats.h"
#include "llcontrol.h"
#include "pipeline.h"
#include "llagentcamera.h"
#include "llvoavatar.h"
#include "llworld.h"
extern LLControlGroup gSavedSettings;
namespace FSPerfStats
{
#ifdef USAGE_TRACKING
std::atomic<int64_t> inUse{0};
std::atomic<int64_t> inUseAvatar{0};
std::atomic<int64_t> inUseScene{0};
std::atomic<int64_t> inUseAttachment{0};
std::atomic<int64_t> inUseAttachmentRigged{0};
std::atomic<int64_t> inUseAttachmentUnRigged{0};
#endif
std::atomic<int64_t> tunedAvatars{0};
U32 targetFPS; // desired FPS
U64 renderAvatarMaxART_ns{(U64)(ART_UNLIMITED_NANOS)}; // highest render time we'll allow without culling features
U32 fpsTuningStrategy{0}; // linked to FSTuningFPSStrategy
U32 lastGlobalPrefChange{0};
std::mutex bufferToggleLock{};
bool autoTune{false};
std::atomic<int> StatsRecorder::writeBuffer{0};
bool StatsRecorder::collectionEnabled{true};
LLUUID StatsRecorder::focusAv{LLUUID::null};
std::array<StatsRecorder::StatsTypeMatrix,2> StatsRecorder::statsDoubleBuffer{ {} };
std::array<StatsRecorder::StatsSummaryArray,2> StatsRecorder::max{ {} };
std::array<StatsRecorder::StatsSummaryArray,2> StatsRecorder::sum{ {} };
StatsRecorder::StatsRecorder():q(1024*16),t(&StatsRecorder::run)
{
// create a queue
// create a thread to consume from the queue
FSPerfStats::targetFPS = gSavedSettings.getU32("FSTargetFPS");
FSPerfStats::autoTune = gSavedSettings.getBOOL("FSAutoTuneFPS");
updateRenderCostLimitFromSettings();
t.detach();
}
// static
void StatsRecorder::toggleBuffer()
{
LL_PROFILE_ZONE_SCOPED;
using ST = StatType_t;
bool unreliable{false};
static LLCachedControl<U32> smoothingPeriods(gSavedSettings, "FSPerfFloaterSmoothingPeriods");
auto& sceneStats = statsDoubleBuffer[writeBuffer][static_cast<size_t>(ObjType_t::OT_GENERAL)][LLUUID::null];
auto& lastStats = statsDoubleBuffer[writeBuffer ^ 1][static_cast<size_t>(ObjType_t::OT_GENERAL)][LLUUID::null];
static constexpr std::initializer_list<StatType_t> sceneStatsToAvg = {
StatType_t::RENDER_FRAME,
StatType_t::RENDER_DISPLAY,
StatType_t::RENDER_HUDS,
StatType_t::RENDER_UI,
StatType_t::RENDER_SWAP,
// RENDER_LFS,
// RENDER_MESHREPO,
StatType_t::RENDER_IDLE };
static constexpr std::initializer_list<StatType_t> avatarStatsToAvg = {
StatType_t::RENDER_GEOMETRY,
StatType_t::RENDER_SHADOWS,
StatType_t::RENDER_COMBINED,
StatType_t::RENDER_IDLE };
if( sceneStats[static_cast<size_t>(StatType_t::RENDER_FPSLIMIT)] != 0 || sceneStats[static_cast<size_t>(StatType_t::RENDER_SLEEP)] != 0 )
{
unreliable = true;
lastStats[static_cast<size_t>(StatType_t::RENDER_FPSLIMIT)] = sceneStats[static_cast<size_t>(StatType_t::RENDER_FPSLIMIT)];
lastStats[static_cast<size_t>(StatType_t::RENDER_SLEEP)] = sceneStats[static_cast<size_t>(StatType_t::RENDER_SLEEP)];
}
if(!unreliable)
{
// only use these stats when things are reliable.
for(auto & statEntry : sceneStatsToAvg)
{
auto avg = lastStats[static_cast<size_t>(statEntry)];
auto val = sceneStats[static_cast<size_t>(statEntry)];
sceneStats[static_cast<size_t>(statEntry)] = avg + (val/smoothingPeriods) - (avg/smoothingPeriods);
// LL_INFOS("scenestats") << "Scenestat: " << static_cast<size_t>(statEntry) << " before=" << avg << " new=" << val << " newavg=" << statsDoubleBuffer[writeBuffer][static_cast<size_t>(ObjType_t::OT_GENERAL)][LLUUID::null][static_cast<size_t>(statEntry)] << LL_ENDL;
}
auto& statsMap = statsDoubleBuffer[writeBuffer][static_cast<size_t>(ObjType_t::OT_ATTACHMENT)];
for(auto& stat_entry : statsMap)
{
auto val = stat_entry.second[static_cast<size_t>(ST::RENDER_COMBINED)];
if(val>smoothingPeriods){
auto avg = statsDoubleBuffer[writeBuffer ^ 1][static_cast<size_t>(ObjType_t::OT_ATTACHMENT)][stat_entry.first][static_cast<size_t>(ST::RENDER_COMBINED)];
stat_entry.second[static_cast<size_t>(ST::RENDER_COMBINED)] = avg + (val/smoothingPeriods) - (avg/smoothingPeriods);
}
}
auto& statsMapAv = statsDoubleBuffer[writeBuffer][static_cast<size_t>(ObjType_t::OT_AVATAR)];
for(auto& stat_entry : statsMapAv)
{
for(auto& stat : avatarStatsToAvg)
{
auto val = stat_entry.second[static_cast<size_t>(stat)];
if(val>smoothingPeriods)
{
auto avg = statsDoubleBuffer[writeBuffer ^ 1][static_cast<size_t>(ObjType_t::OT_AVATAR)][stat_entry.first][static_cast<size_t>(stat)];
stat_entry.second[static_cast<size_t>(stat)] = avg + (val/smoothingPeriods) - (avg/smoothingPeriods);
}
}
}
// swap the buffers
if(enabled())
{
std::lock_guard<std::mutex> lock{bufferToggleLock};
writeBuffer ^= 1;
}; // note we are relying on atomic updates here. The risk is low and would cause minor errors in the stats display.
}
// clean the write maps in all cases.
auto& statsTypeMatrix = statsDoubleBuffer[writeBuffer];
for(auto& statsMap : statsTypeMatrix)
{
LL_PROFILE_ZONE_NAMED("Clear stats maps");
for(auto& stat_entry : statsMap)
{
std::fill_n(stat_entry.second.begin() ,static_cast<size_t>(ST::STATS_COUNT),0);
}
statsMap.clear();
}
for(int i=0; i< static_cast<size_t>(ObjType_t::OT_COUNT); i++)
{
LL_PROFILE_ZONE_NAMED("clear max/sum");
max[writeBuffer][i].fill(0);
sum[writeBuffer][i].fill(0);
}
// and now adjust the visuals.
if(autoTune)
{
updateAvatarParams();
}
}
// clear buffers when we change region or need a hard reset.
// static
void StatsRecorder::clearStatsBuffers()
{
LL_PROFILE_ZONE_SCOPED;
using ST = StatType_t;
auto& statsTypeMatrix = statsDoubleBuffer[writeBuffer];
for(auto& statsMap : statsTypeMatrix)
{
LL_PROFILE_ZONE_NAMED("Clear stats maps");
for(auto& stat_entry : statsMap)
{
std::fill_n(stat_entry.second.begin() ,static_cast<size_t>(ST::STATS_COUNT),0);
}
statsMap.clear();
}
for(int i=0; i< static_cast<size_t>(ObjType_t::OT_COUNT); i++)
{
LL_PROFILE_ZONE_NAMED("clear max/sum");
max[writeBuffer][i].fill(0);
sum[writeBuffer][i].fill(0);
}
// swap the clean buffers in
if(enabled())
{
std::lock_guard<std::mutex> lock{bufferToggleLock};
writeBuffer ^= 1;
};
// repeat before we start processing new stuff
for(auto& statsMap : statsTypeMatrix)
{
LL_PROFILE_ZONE_NAMED("Clear stats maps");
for(auto& stat_entry : statsMap)
{
std::fill_n(stat_entry.second.begin() ,static_cast<size_t>(ST::STATS_COUNT),0);
}
statsMap.clear();
}
for(int i=0; i< static_cast<size_t>(ObjType_t::OT_COUNT); i++)
{
LL_PROFILE_ZONE_NAMED("clear max/sum");
max[writeBuffer][i].fill(0);
sum[writeBuffer][i].fill(0);
}
}
// static
void StatsRecorder::updateSettingsFromRenderCostLimit()
{
static LLCachedControl<F32> maxRenderCost_us(gSavedSettings, "FSRenderAvatarMaxART");
if( (F32)maxRenderCost_us != log10( ( (F32)FSPerfStats::renderAvatarMaxART_ns )/1000 ) )
{
if( FSPerfStats::renderAvatarMaxART_ns != 0 )
{
gSavedSettings.setF32( "FSRenderAvatarMaxART", log10( ( (F32)FSPerfStats::renderAvatarMaxART_ns )/1000 ) );
}
else
{
gSavedSettings.setF32( "FSRenderAvatarMaxART",log10( FSPerfStats::ART_UNLIMITED_NANOS/1000 ) );
}
}
}
// static
void StatsRecorder::updateRenderCostLimitFromSettings()
{
const auto newval = gSavedSettings.getF32("FSRenderAvatarMaxART");
if(newval < log10(FSPerfStats::ART_UNLIMITED_NANOS/1000))
{
FSPerfStats::renderAvatarMaxART_ns = pow(10,newval)*1000;
}
else
{
FSPerfStats::renderAvatarMaxART_ns = 0;
};
}
//static
int StatsRecorder::countNearbyAvatars(S32 distance)
{
const auto our_pos = gAgentCamera.getCameraPositionGlobal();
std::vector<LLVector3d> positions;
uuid_vec_t avatar_ids;
LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, our_pos, distance);
return positions.size();
}
// static
void StatsRecorder::updateAvatarParams()
{
static LLCachedControl<F32> drawDistance(gSavedSettings, "RenderFarClip");
static LLCachedControl<F32> userMinDrawDistance(gSavedSettings, "FSAutoTuneRenderFarClipMin");
static LLCachedControl<F32> userTargetDrawDistance(gSavedSettings, "FSAutoTuneRenderFarClipTarget");
static LLCachedControl<F32> impostorDistance(gSavedSettings, "FSAutoTuneImpostorFarAwayDistance");
static LLCachedControl<bool> impostorDistanceTuning(gSavedSettings, "FSAutoTuneImpostorByDistEnabled");
static LLCachedControl<U32> maxNonImpostors (gSavedSettings, "IndirectMaxNonImpostors");
if(impostorDistanceTuning)
{
// if we have less than the user's "max Non-Impostors" avatars within the desired range then adjust the limit.
// also adjusts back up again for nearby crowds.
auto count = countNearbyAvatars(std::min(drawDistance, impostorDistance));
if( count != maxNonImpostors )
{
gSavedSettings.setU32("IndirectMaxNonImpostors", (count < LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER)?count : LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER);
LL_DEBUGS("AutoTune") << "There are " << count << "avatars within " << std::min(drawDistance, impostorDistance) << "m of the camera" << LL_ENDL;
}
}
auto av_render_max_raw = FSPerfStats::StatsRecorder::getMax(ObjType_t::OT_AVATAR, FSPerfStats::StatType_t::RENDER_COMBINED);
// Is our target frame time lower than current? If so we need to take action to reduce draw overheads.
// cumulative avatar time (includes idle processing, attachments and base av)
auto tot_avatar_time_raw = FSPerfStats::StatsRecorder::getSum(ObjType_t::OT_AVATAR, FSPerfStats::StatType_t::RENDER_COMBINED);
// sleep time is basically forced sleep when window out of focus
auto tot_sleep_time_raw = FSPerfStats::StatsRecorder::getSceneStat(FSPerfStats::StatType_t::RENDER_SLEEP);
// similar to sleep time, induced by FPS limit
auto tot_limit_time_raw = FSPerfStats::StatsRecorder::getSceneStat(FSPerfStats::StatType_t::RENDER_FPSLIMIT);
// the time spent this frame on the "doFrame" call. Treated as "tot time for frame"
auto tot_frame_time_raw = FSPerfStats::StatsRecorder::getSceneStat(FSPerfStats::StatType_t::RENDER_FRAME);
if( tot_sleep_time_raw != 0 )
{
// Note: we do not average sleep
// if at some point we need to, the averaging will need to take this into account or
// we forever think we're in the background due to residuals.
LL_DEBUGS() << "No tuning when not in focus" << LL_ENDL;
return;
}
// The frametime budget we have based on the target FPS selected
auto target_frame_time_raw = (U64)llround((F64)LLTrace::BlockTimer::countsPerSecond()/(targetFPS==0?1:targetFPS));
// LL_INFOS() << "Effective FPS(raw):" << tot_frame_time_raw << " Target:" << target_frame_time_raw << LL_ENDL;
if( tot_limit_time_raw != 0)
{
// This could be problematic.
tot_frame_time_raw -= tot_limit_time_raw;
}
// 1) Is the target frame tim lower than current?
if( target_frame_time_raw <= tot_frame_time_raw )
{
// if so we've got work to do
// how much of the frame was spent on non avatar related work?
U32 non_avatar_time_raw = tot_frame_time_raw - tot_avatar_time_raw;
// If the target frame time < non avatar frame time thne adjusting avatars is only goin gto get us so far.
U64 target_avatar_time_raw;
if(target_frame_time_raw < non_avatar_time_raw)
{
// we cannnot do this by avatar adjustment alone.
if((gFrameCount - FSPerfStats::lastGlobalPrefChange) > 10) // give changes a short time to take effect.
{
if(FSPerfStats::fpsTuningStrategy == 1)
{
// 1 - hack the water to opaque. all non opaque have a significant hit, this is a big boost for (arguably) a minor visual hit.
// the other reflection options make comparatively little change and iof this overshoots we'll be stepping back up later
if(LLPipeline::RenderReflectionDetail != -2)
{
gSavedSettings.setS32("RenderReflectionDetail", -2);
FSPerfStats::lastGlobalPrefChange = gFrameCount;
return;
}
else // deliberately "else" here so we only do these in steps
{
// step down the DD by 10m per update
auto new_dd = (drawDistance-10>userMinDrawDistance)?(drawDistance - 10) : userMinDrawDistance;
if(new_dd != drawDistance)
{
gSavedSettings.setF32("RenderFarClip", new_dd);
FSPerfStats::lastGlobalPrefChange = gFrameCount;
return;
}
}
}
}
target_avatar_time_raw = 0;
}
else
{
// desired avatar budget.
target_avatar_time_raw = target_frame_time_raw - non_avatar_time_raw;
}
if( target_avatar_time_raw < tot_avatar_time_raw )
{
// we need to spend less time drawing avatars to meet our budget
// Note: working in usecs now cos reasons.
auto new_render_limit_ns {renderAvatarMaxART_ns};
// max render this frame may be higher than the last (cos new entrants and jitter) so make sure we are heading in the right direction
if(FSPerfStats::raw_to_ns(av_render_max_raw) < renderAvatarMaxART_ns)
{
new_render_limit_ns = FSPerfStats::raw_to_ns(av_render_max_raw);
}
else
{
new_render_limit_ns = renderAvatarMaxART_ns;
}
new_render_limit_ns -= FSPerfStats::ART_MIN_ADJUST_DOWN_NANOS;
// bounce at the bottom to prevent "no limit"
new_render_limit_ns = std::max((U64)new_render_limit_ns, (U64)FSPerfStats::ART_MINIMUM_NANOS);
// assign the new value
renderAvatarMaxART_ns = new_render_limit_ns;
// LL_DEBUGS() << "AUTO_TUNE: avatar_budget adjusted to:" << new_render_limit_ns << LL_ENDL;
}
// LL_DEBUGS() << "AUTO_TUNE: Target frame time:"<< FSPerfStats::raw_to_us(target_frame_time_raw) << "usecs (non_avatar is " << FSPerfStats::raw_to_us(non_avatar_time_raw) << "usecs) Max cost limited=" << renderAvatarMaxART_ns << LL_ENDL;
}
else if( FSPerfStats::raw_to_ns(target_frame_time_raw) > (FSPerfStats::raw_to_ns(tot_frame_time_raw) + renderAvatarMaxART_ns) )
{
if( FSPerfStats::tunedAvatars >= 0 )
{
// if we have more time to spare let's shift up little in the hope we'll restore an avatar.
renderAvatarMaxART_ns += FSPerfStats::ART_MIN_ADJUST_UP_NANOS;
}
if( drawDistance < userTargetDrawDistance )
{
gSavedSettings.setF32("RenderFarClip", drawDistance + 10.);
}
if( (target_frame_time_raw * 1.5) > tot_frame_time_raw &&
FSPerfStats::tunedAvatars == 0 &&
drawDistance >= userTargetDrawDistance)
{
// if everything else is "max" and we have 50% headroom let's knock the water quality up a notch at a time.
auto water = gSavedSettings.getS32("RenderReflectionDetail");
gSavedSettings.setS32("RenderReflectionDetail", water+1);
}
}
updateSettingsFromRenderCostLimit();
}
}

498
indra/newview/fsperfstats.h Normal file
View File

@ -0,0 +1,498 @@
#pragma once
#ifndef FS_PERFSTATS_H_INCLUDED
#define FS_PERFSTATS_H_INCLUDED
/**
* @file fsperfstats.h
* @brief Statistics collection to support autotune and perf flaoter.
*
* $LicenseInfo:firstyear=2021&license=fsviewerlgpl$
* Phoenix Firestorm Viewer Source Code
* Copyright (C) 2021, The Phoenix Firestorm Project, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
* http://www.firestormviewer.org
* $/LicenseInfo$
*/
#include <atomic>
#include <chrono>
#include <array>
#include <unordered_map>
#include <mutex>
#include "lluuid.h"
#include "llfasttimer.h"
#include "blockingconcurrentqueue.h"
#include "llapp.h"
#include "llprofiler.h"
#include "pipeline.h"
// Additional logging options. These can skew inworld numbers so onyl use for debugging and tracking issues
#ifdef FS_HAS_TELEMETRY_SUPPORT
// USAGE_TRACKING - displays overlapping stats that may imply double counting.
// ATTACHMENT_TRACKING - displays detailed tracking info for Avatar and Attachment. very heavy overhead.
// #define USAGE_TRACKING
// #define ATTACHMENT_TRACKING
#else
#undef USAGE_TRACKING
#undef ATTACHMENT_TRACKING
#endif
extern U32 gFrameCount;
extern LLUUID gAgentID;
namespace FSPerfStats
{
#ifdef USAGE_TRACKING
extern std::atomic<int64_t> inUse;
extern std::atomic<int64_t> inUseAvatar;
extern std::atomic<int64_t> inUseScene;
extern std::atomic<int64_t> inUseAttachment;
extern std::atomic<int64_t> inUseAttachmentRigged;
extern std::atomic<int64_t> inUseAttachmentUnRigged;
#endif
// Note if changing these, they should correspond with the log range of the correpsonding sliders
constexpr U64 ART_UNLIMITED_NANOS{50000000};
constexpr U64 ART_MINIMUM_NANOS{100000};
constexpr U64 ART_MIN_ADJUST_UP_NANOS{10000};
constexpr U64 ART_MIN_ADJUST_DOWN_NANOS{10000};
constexpr F32 PREFERRED_DD{180};
extern std::atomic<int64_t> tunedAvatars;
extern U32 targetFPS; // desired FPS
extern U64 renderAvatarMaxART_ns;
extern U32 fpsTuningStrategy;
extern U32 lastGlobalPrefChange;
extern std::mutex bufferToggleLock;
extern bool autoTune;
enum class ObjType_t{
OT_GENERAL=0, // Also Unknown. Used for n/a type stats such as scenery
OT_AVATAR,
OT_ATTACHMENT,
OT_HUD,
OT_COUNT
};
enum class StatType_t{
RENDER_GEOMETRY=0,
RENDER_SHADOWS,
RENDER_HUDS,
RENDER_UI,
RENDER_COMBINED,
RENDER_SWAP,
RENDER_FRAME,
RENDER_DISPLAY,
RENDER_SLEEP,
RENDER_LFS,
RENDER_MESHREPO,
RENDER_FPSLIMIT,
RENDER_FPS,
RENDER_IDLE,
RENDER_DONE, // toggle buffer & clearbuffer (see processUpdate for hackery)
STATS_COUNT
};
struct StatsRecord
{
StatType_t statType;
ObjType_t objType;
LLUUID avID;
LLUUID objID;
uint64_t time;
bool isRigged;
bool isHUD;
};
class StatsRecorder{
using Queue = moodycamel::BlockingConcurrentQueue<StatsRecord>;
public:
static inline StatsRecorder& getInstance()
{
static StatsRecorder instance;
// volatile int dummy{};
return instance;
}
static inline void setFocusAv(const LLUUID& avID){focusAv = avID;};
static inline const LLUUID& getFocusAv(){return (focusAv);};
static inline void send(StatsRecord&& u){StatsRecorder::getInstance().q.enqueue(u);};
static void endFrame(){StatsRecorder::getInstance().q.enqueue(StatsRecord{StatType_t::RENDER_DONE, ObjType_t::OT_GENERAL, LLUUID::null, LLUUID::null, 0});};
static void clearStats(){StatsRecorder::getInstance().q.enqueue(StatsRecord{StatType_t::RENDER_DONE, ObjType_t::OT_GENERAL, LLUUID::null, LLUUID::null, 1});};
static inline void setEnabled(bool on_or_off){collectionEnabled=on_or_off;};
static inline void enable() { collectionEnabled=true; };
static inline void disable() { collectionEnabled=false; };
static inline bool enabled() { return(collectionEnabled); };
static inline int getReadBufferIndex() { return (writeBuffer ^ 1); };
// static inline const StatsTypeMatrix& getCurrentStatsMatrix(){ return statsDoubleBuffer[getReadBufferIndex()];}
static inline uint64_t get(ObjType_t otype, LLUUID id, StatType_t type)
{
return statsDoubleBuffer[getReadBufferIndex()][static_cast<size_t>(otype)][id][static_cast<size_t>(type)];
}
static inline uint64_t getSceneStat(StatType_t type)
{
return statsDoubleBuffer[getReadBufferIndex()][static_cast<size_t>(ObjType_t::OT_GENERAL)][LLUUID::null][static_cast<size_t>(type)];
}
static inline uint64_t getSum(ObjType_t otype, StatType_t type)
{
return sum[getReadBufferIndex()][static_cast<size_t>(otype)][static_cast<size_t>(type)];
}
static inline uint64_t getMax(ObjType_t otype, StatType_t type)
{
return max[getReadBufferIndex()][static_cast<size_t>(otype)][static_cast<size_t>(type)];
}
static void updateSettingsFromRenderCostLimit();
static void updateRenderCostLimitFromSettings();
static void updateAvatarParams();
private:
StatsRecorder();
static int countNearbyAvatars(S32 distance);
// StatsArray is a uint64_t for each possible statistic type.
using StatsArray = std::array<uint64_t, static_cast<size_t>(FSPerfStats::StatType_t::STATS_COUNT)>;
using StatsMap = std::unordered_map<LLUUID, StatsArray, FSUUIDHash>;
using StatsTypeMatrix = std::array<StatsMap, static_cast<size_t>(FSPerfStats::ObjType_t::OT_COUNT)>;
using StatsSummaryArray = std::array<StatsArray, static_cast<size_t>(FSPerfStats::ObjType_t::OT_COUNT)>;
static std::atomic<int> writeBuffer;
static LLUUID focusAv;
static std::array<StatsTypeMatrix,2> statsDoubleBuffer;
static std::array<StatsSummaryArray,2> max;
static std::array<StatsSummaryArray,2> sum;
static bool collectionEnabled;
void processUpdate(const StatsRecord& upd)
{
LL_PROFILE_ZONE_SCOPED;
// LL_INFOS("perfstats") << "processing update:" << LL_ENDL;
using ST = StatType_t;
// Note: nullptr is used as the key for global stats
#ifdef FS_HAS_TELEMETRY_SUPPORT
static char avstr[36];
static char obstr[36];
#endif
if (upd.statType == StatType_t::RENDER_DONE && upd.objType == ObjType_t::OT_GENERAL && upd.time == 0)
{
// LL_INFOS("perfstats") << "End of Frame Toggle Buffer:" << gFrameCount << LL_ENDL;
toggleBuffer();
return;
}
if (upd.statType == StatType_t::RENDER_DONE && upd.objType == ObjType_t::OT_GENERAL && upd.time == 1)
{
// LL_INFOS("perfstats") << "New region - clear buffers:" << gFrameCount << LL_ENDL;
clearStatsBuffers();
return;
}
auto ot{upd.objType};
auto& key{upd.objID};
auto& avKey{upd.avID};
auto type {upd.statType};
auto val {upd.time};
#ifdef FS_HAS_TELEMETRY_SUPPORT
LL_PROFILE_ZONE_TEXT(key.toStringFast(obstr), 36);
LL_PROFILE_ZONE_TEXT(avKey.toStringFast(avstr), 36);
LL_PROFILE_ZONE_NUM(val);
#endif
if (ot == ObjType_t::OT_GENERAL)
{
// LL_INFOS("perfstats") << "General update:" << LL_ENDL;
doUpd(key, ot, type,val);
return;
}
if (ot == ObjType_t::OT_AVATAR)
{
// LL_INFOS("perfstats") << "Avatar update:" << LL_ENDL;
doUpd(avKey, ot, type, val);
return;
}
if (ot == ObjType_t::OT_ATTACHMENT)
{
if( !upd.isRigged && !upd.isHUD )
{
// For all attachments that are not rigged we add them to the avatar (for all avatars) cost.
doUpd(avKey, ObjType_t::OT_AVATAR, type, val);
}
if( avKey == focusAv )
{
// For attachments that are for the focusAv (self for now) we record them for the attachment/complexity view
if(upd.isHUD)
{
ot = ObjType_t::OT_HUD;
}
// LL_INFOS("perfstats") << "frame: " << gFrameCount << " Attachment update("<< (type==StatType_t::RENDER_GEOMETRY?"GEOMETRY":"SHADOW") << ": " << key.asString() << " = " << val << LL_ENDL;
doUpd(key, ot, type, val);
}
else
{
// LL_INFOS("perfstats") << "frame: " << gFrameCount << " non-self Att update("<< (type==StatType_t::RENDER_GEOMETRY?"GEOMETRY":"SHADOW") << ": " << key.asString() << " = " << val << " for av " << avKey.asString() << LL_ENDL;
}
}
}
static inline void doUpd(const LLUUID& key, ObjType_t ot, StatType_t type, uint64_t val)
{
LL_PROFILE_ZONE_SCOPED;
using ST = StatType_t;
StatsMap& stm {statsDoubleBuffer[writeBuffer][static_cast<size_t>(ot)]};
auto& thisAsset = stm[key];
thisAsset[static_cast<size_t>(type)] += val;
thisAsset[static_cast<size_t>(ST::RENDER_COMBINED)] += val;
sum[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(type)] += val;
sum[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(ST::RENDER_COMBINED)] += val;
if(max[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(type)] < thisAsset[static_cast<size_t>(type)])
{
max[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(type)] = thisAsset[static_cast<size_t>(type)];
}
if(max[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(ST::RENDER_COMBINED)] < thisAsset[static_cast<size_t>(ST::RENDER_COMBINED)])
{
max[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(ST::RENDER_COMBINED)] = thisAsset[static_cast<size_t>(ST::RENDER_COMBINED)];
}
}
static void toggleBuffer();
static void clearStatsBuffers();
// thread entry
static void run()
{
StatsRecord upd[10];
auto& instance {StatsRecorder::getInstance()};
LL_PROFILER_THREAD_BEGIN("PerfStats");
while( enabled() && !LLApp::isExiting() )
{
auto count = instance.q.wait_dequeue_bulk_timed(upd, 10, std::chrono::milliseconds(10));
if(count)
{
// LL_INFOS("perfstats") << "processing " << count << " updates." << LL_ENDL;
for(auto i =0; i < count; i++)
{
instance.processUpdate(upd[i]);
}
}
}
LL_PROFILER_THREAD_END("PerfStats");
}
Queue q;
std::thread t;
~StatsRecorder() = default;
StatsRecorder(const StatsRecorder&) = delete;
StatsRecorder& operator=(const StatsRecorder&) = delete;
};
template <enum ObjType_t ObjTypeDiscriminator>
class RecordTime
{
private:
RecordTime(const RecordTime&) = delete;
RecordTime() = delete;
U64 start;
public:
StatsRecord stat;
RecordTime( const LLUUID& av, const LLUUID& id, StatType_t type, bool isRiggedAtt=false, bool isHUDAtt=false):
start{LLTrace::BlockTimer::getCPUClockCount64()},
stat{type, ObjTypeDiscriminator, std::move(av), std::move(id), 0, isRiggedAtt, isHUDAtt}
{
LL_PROFILE_ZONE_COLOR(tracy::Color::Orange);
#ifdef USAGE_TRACKING
if(stat.objType == FSPerfStats::ObjType_t::OT_ATTACHMENT)
{
if(!stat.isRigged && FSPerfStats::inUseAvatar){FSZoneText("OVERLAP AVATAR",14);}
LL_PROFILE_PLOT_SQ("InUse", (int64_t)FSPerfStats::inUse, (int64_t)FSPerfStats::inUse+1);
FSPerfStats::inUse++;
LL_PROFILE_PLOT_SQ("InUseAttachment", (int64_t)FSPerfStats::inUseAttachment, (int64_t)FSPerfStats::inUseAttachment+1);
FSPerfStats::inUseAttachment++;
if (stat.isRigged)
{
LL_PROFILE_PLOT_SQ("InUseAttachmentRigged", (int64_t)FSPerfStats::inUseAttachmentRigged,(int64_t)FSPerfStats::inUseAttachmentRigged+1);
FSPerfStats::inUseAttachmentRigged++;
}
else
{
LL_PROFILE_PLOT_SQ("InUseAttachmentUnRigged", (int64_t)FSPerfStats::inUseAttachmentUnRigged,(int64_t)FSPerfStats::inUseAttachmentUnRigged+1);
FSPerfStats::inUseAttachmentUnRigged++;
}
}
#endif
};
template < ObjType_t OD = ObjTypeDiscriminator,
std::enable_if_t<OD == ObjType_t::OT_GENERAL> * = nullptr>
RecordTime( StatType_t type ):RecordTime<ObjTypeDiscriminator>(LLUUID::null, LLUUID::null, type )
{
LL_PROFILE_ZONE_SCOPED;
#ifdef USAGE_TRACKING
LL_PROFILE_PLOT_SQ("InUseScene", (int64_t)FSPerfStats::inUseScene, (int64_t)FSPerfStats::inUseScene+1);
FSPerfStats::inUseScene++;
LL_PROFILE_PLOT_SQ("InUse", (int64_t)FSPerfStats::inUse, (int64_t)FSPerfStats::inUse+1);
FSPerfStats::inUse++;
#endif
};
template < ObjType_t OD = ObjTypeDiscriminator,
std::enable_if_t<OD == ObjType_t::OT_AVATAR> * = nullptr>
RecordTime( const LLUUID & av, StatType_t type ):RecordTime<ObjTypeDiscriminator>(std::move(av), LLUUID::null, type)
{
LL_PROFILE_ZONE_COLOR(tracy::Color::Purple);
#ifdef USAGE_TRACKING
if(FSPerfStats::inUseAvatar){FSZoneText("OVERLAP AVATAR",14);}
LL_PROFILE_PLOT_SQ("InUseAv", (int64_t)FSPerfStats::inUseAvatar, (int64_t)FSPerfStats::inUseAvatar+1);
FSPerfStats::inUseAvatar++;
LL_PROFILE_PLOT_SQ("InUse", (int64_t)FSPerfStats::inUse, (int64_t)FSPerfStats::inUse+1);
FSPerfStats::inUse++;
#endif
};
~RecordTime()
{
if(!FSPerfStats::StatsRecorder::enabled())
{
return;
}
LL_PROFILE_ZONE_COLOR(tracy::Color::Red);
#ifdef USAGE_TRACKING
LL_PROFILE_PLOT_SQ("InUse", (int64_t)FSPerfStats::inUse,(int64_t)FSPerfStats::inUse-1);
--FSPerfStats::inUse;
if (stat.objType == FSPerfStats::ObjType_t::OT_ATTACHMENT)
{
LL_PROFILE_PLOT_SQ("InUseAttachment", (int64_t)FSPerfStats::inUseAttachment,(int64_t)FSPerfStats::inUseAttachment-1);
--FSPerfStats::inUseAttachment;
if (stat.isRigged)
{
LL_PROFILE_PLOT_SQ("InUseAttachmentRigged", (int64_t)FSPerfStats::inUseAttachmentRigged,(int64_t)FSPerfStats::inUseAttachmentRigged-1);
--FSPerfStats::inUseAttachmentRigged;
}
else
{
LL_PROFILE_PLOT_SQ("InUseAttachmentUnRigged", (int64_t)FSPerfStats::inUseAttachmentUnRigged,(int64_t)FSPerfStats::inUseAttachmentUnRigged-1);
--FSPerfStats::inUseAttachmentUnRigged;
}
}
if (stat.objType == FSPerfStats::ObjType_t::OT_GENERAL)
{
LL_PROFILE_PLOT_SQ("InUseScene", (int64_t)FSPerfStats::inUseScene,(int64_t)FSPerfStats::inUseScene-1);
--FSPerfStats::inUseScene;
}
if( stat.objType == FSPerfStats::ObjType_t::OT_AVATAR )
{
LL_PROFILE_PLOT_SQ("InUseAv", (int64_t)FSPerfStats::inUseAvatar, (int64_t)FSPerfStats::inUseAvatar-1);
--FSPerfStats::inUseAvatar;
}
#endif
stat.time = LLTrace::BlockTimer::getCPUClockCount64() - start;
#ifdef ATTACHMENT_TRACKING
static char obstr[36];
static char avstr[36];
LL_PROFILE_ZONE_NUM(static_cast<U64>(stat.objType));
LL_PROFILE_ZONE_TEXT(stat.avID.toStringFast(avstr), 36);
LL_PROFILE_ZONE_TEXT(stat.objID.toStringFast(obstr), 36);
LL_PROFILE_ZONE_NUM(stat.time);
#endif
StatsRecorder::send(std::move(stat));
};
};
inline double raw_to_ns(U64 raw) { return (static_cast<double>(raw) * 1000000000.0) / (F64)LLTrace::BlockTimer::countsPerSecond(); };
inline double raw_to_us(U64 raw) { return (static_cast<double>(raw) * 1000000.0) / (F64)LLTrace::BlockTimer::countsPerSecond(); };
inline double raw_to_ms(U64 raw) { return (static_cast<double>(raw) * 1000.0) / (F64)LLTrace::BlockTimer::countsPerSecond(); };
using RecordSceneTime = RecordTime<ObjType_t::OT_GENERAL>;
using RecordAvatarTime = RecordTime<ObjType_t::OT_AVATAR>;
using RecordAttachmentTime = RecordTime<ObjType_t::OT_ATTACHMENT>;
using RecordHudAttachmentTime = RecordTime<ObjType_t::OT_HUD>;
};// namespace FSPerfStats
// helper functions
using RATptr = std::unique_ptr<FSPerfStats::RecordAttachmentTime>;
template <typename T>
static inline void trackAttachments(const T * vobj, bool isRigged, RATptr* ratPtrp)
{
if( !vobj ){ ratPtrp->reset(); return;};
const T* rootAtt{vobj};
if (rootAtt->isAttachment())
{
LL_PROFILE_ZONE_SCOPED;
while( !rootAtt->isRootEdit() )
{
rootAtt = (T*)(rootAtt->getParent());
}
auto avPtr = (T*)(rootAtt->getParent());
if(!avPtr){ratPtrp->reset(); return;}
auto& av = avPtr->getID();
auto& obj = rootAtt->getAttachmentItemID();
if (!*ratPtrp || (*ratPtrp)->stat.objID != obj || (*ratPtrp)->stat.avID != av)
{
#if TRACY_ENABLE && defined(ATTACHMENT_TRACKING)
LL_PROFILE_ZONE_NAMED_COLOR( "trackAttachments:new", tracy::Color::Red);
auto& str = rootAtt->getAttachmentItemName();
LL_PROFILE_ZONE_TEXT(str.c_str(), str.size());
LL_PROFILE_ZONE_TEXT(isRigged ? "Rigged" : "Unrigged", 8);
static char avStr[36];
av.toStringFast(avStr);
static char obStr[4];
obj.toShortString(obStr);
LL_PROFILE_ZONE_TEXT( avStr, 36);
LL_PROFILE_ZONE_TEXT( obStr, 4);
#endif
if (*ratPtrp)
{
// deliberately reset to ensure destruction before construction of replacement.
ratPtrp->reset();
};
*ratPtrp = std::make_unique<FSPerfStats::RecordAttachmentTime>( av,
obj,
( (LLPipeline::sShadowRender)?FSPerfStats::StatType_t::RENDER_SHADOWS : FSPerfStats::StatType_t::RENDER_GEOMETRY ),
isRigged,
rootAtt->isHUDAttachment());
}
}
return;
};
#endif

View File

@ -285,6 +285,7 @@
#include "fsassetblacklist.h"
// #include "fstelemetry.h" // <FS:Beq> Tracy profiler support
#include "fsperfstats.h" // <FS:Beq> performance stats support
#if LL_LINUX && LL_GTK
#include "glib.h"
@ -1570,6 +1571,7 @@ void LLAppViewer::initMaxHeapSize()
}
static LLTrace::BlockTimerStatHandle FTM_MESSAGES("System Messages");
static LLTrace::BlockTimerStatHandle FTM_MESSAGES2("System Messages2");
static LLTrace::BlockTimerStatHandle FTM_SLEEP1("Sleep1");
static LLTrace::BlockTimerStatHandle FTM_SLEEP2("Sleep2");
static LLTrace::BlockTimerStatHandle FTM_YIELD("Yield");
@ -1634,6 +1636,9 @@ bool LLAppViewer::doFrame()
{
LL_RECORD_BLOCK_TIME(FTM_FRAME);
// <FS:Beq> Perfstats collection Frame boundary
{FSPerfStats::RecordSceneTime T (FSPerfStats::StatType_t::RENDER_FRAME);
LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
LLSD newFrame;
// <FS:Beq> profiling enablement.
@ -1677,6 +1682,7 @@ bool LLAppViewer::doFrame()
LLTimer frameTimer;
nd::etw::logFrame(); // <FS:ND> Write the start of each frame. Even if our Provider (Firestorm) would be enabled, this has only light impact. Does nothing on OSX and Linux.
{FSPerfStats::RecordSceneTime T (FSPerfStats::StatType_t::RENDER_IDLE); // <FS:Beq/> perf stats
{
LL_PROFILE_ZONE_NAMED( "df blocktimer" )
LLTrace::BlockTimer::processTimes();
@ -1688,9 +1694,9 @@ bool LLAppViewer::doFrame()
//clear call stack records
LL_CLEAR_CALLSTACKS();
} // <FS:Beq/> perf stats
{
// LL_PROFILE_ZONE_NAMED( "df processMiscNativeEvents" ) // <FS:Beq/> remove misplaced zone marker (see FTM_MESSAGES)
{FSPerfStats::RecordSceneTime T (FSPerfStats::StatType_t::RENDER_IDLE); // <FS:Beq> ensure we have the entire top scope of frame covered
// <FS:Ansariel> MaxFPS Viewer-Chui merge error
// Check if we need to restore rendering masks.
if (restore_rendering_masks)
@ -1731,7 +1737,7 @@ bool LLAppViewer::doFrame()
if (gViewerWindow)
{
LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
LL_RECORD_BLOCK_TIME(FTM_MESSAGES2);
if (!restoreErrorTrap())
{
LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL;
@ -1756,12 +1762,12 @@ bool LLAppViewer::doFrame()
// canonical per-frame event
mainloop.post(newFrame);
}
{
LL_PROFILE_ZONE_NAMED( "df suspend" )
// give listeners a chance to run
llcoro::suspend();
}
}// <FS:Beq> ensure we have the entire top scope of frame covered
if (!LLApp::isExiting())
{
@ -1778,6 +1784,7 @@ bool LLAppViewer::doFrame()
&& (gHeadlessClient || !gViewerWindow->getShowProgress())
&& !gFocusMgr.focusLocked())
{
FSPerfStats::RecordSceneTime T (FSPerfStats::StatType_t::RENDER_IDLE);
LL_PROFILE_ZONE_NAMED( "df JoystickKeyboard" )
joystick->scanJoystick();
gKeyboard->scanKeyboard();
@ -1788,12 +1795,13 @@ bool LLAppViewer::doFrame()
if (fsCrouchToggle && fsCrouchToggleStatus)
{
gAgent.moveUp(-1);
}
}
// </FS:Ansariel>
}
// Update state based on messages, user input, object idle.
{
FSPerfStats::RecordSceneTime T (FSPerfStats::StatType_t::RENDER_IDLE);
LL_PROFILE_ZONE_NAMED( "df pauseMainloopTimeout" )
pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
}
@ -1810,6 +1818,7 @@ bool LLAppViewer::doFrame()
if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
{
LL_PROFILE_ZONE_NAMED("Shutdown:SaveSnapshot");
pauseMainloopTimeout();
saveFinalSnapshot();
disconnectViewer();
@ -1820,7 +1829,7 @@ bool LLAppViewer::doFrame()
// *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
if (!LLApp::isExiting() && !gHeadlessClient && gViewerWindow)
{
LL_PROFILE_ZONE_NAMED( "df Display" )
LL_PROFILE_ZONE_NAMED("df Display")
pingMainloopTimeout("Main:Display");
gGLActive = TRUE;
@ -1844,14 +1853,15 @@ bool LLAppViewer::doFrame()
//last_call = LLTimer::getTotalTime();
// </FS:Ansariel>
}
{
LL_PROFILE_ZONE_NAMED( "df Snapshot" )
FSPerfStats::RecordSceneTime T(FSPerfStats::StatType_t::RENDER_IDLE);
LL_PROFILE_ZONE_NAMED("df Snapshot")
pingMainloopTimeout("Main:Snapshot");
LLFloaterSnapshot::update(); // take snapshots
LLFloaterOutfitSnapshot::update();
gGLActive = FALSE;
}
}
}
{
@ -1888,6 +1898,7 @@ bool LLAppViewer::doFrame()
// of equal priority on Windows
if (milliseconds_to_sleep > 0)
{
FSPerfStats::RecordSceneTime T ( FSPerfStats::StatType_t::RENDER_SLEEP );
ms_sleep(milliseconds_to_sleep);
// also pause worker threads during this wait period
LLAppViewer::getTextureCache()->pause();
@ -1972,6 +1983,7 @@ bool LLAppViewer::doFrame()
if (fsLimitFramerate && LLStartUp::getStartupState() == STATE_STARTED && !gTeleportDisplay && !logoutRequestSent() && max_fps > F_APPROXIMATELY_ZERO)
{
// Sleep a while to limit frame rate.
FSPerfStats::RecordSceneTime T ( FSPerfStats::StatType_t::RENDER_FPSLIMIT );
F32 min_frame_time = 1.f / (F32)max_fps;
S32 milliseconds_to_sleep = llclamp((S32)((min_frame_time - frameTimer.getElapsedTimeF64()) * 1000.f), 0, 1000);
if (milliseconds_to_sleep > 0)
@ -2011,6 +2023,7 @@ bool LLAppViewer::doFrame()
LL_INFOS() << "Exiting main_loop" << LL_ENDL;
}
}FSPerfStats::StatsRecorder::endFrame();
LL_PROFILER_FRAME_END
return ! LLApp::isRunning();
@ -5833,6 +5846,7 @@ void LLAppViewer::idle()
if (!(logoutRequestSent() && hasSavedFinalSnapshot()))
{
FSPerfStats::tunedAvatars=0; // <FS:Beq> reset the number of avatars that have been tweaked.
gObjectList.update(gAgent);
}
}

View File

@ -244,6 +244,12 @@ void LLAvatarRenderNotifier::updateNotificationAgent(U32 agentComplexity)
// save the value for use in following messages
mLatestAgentComplexity = agentComplexity;
static LLCachedControl<U32> show_my_complexity_changes(gSavedSettings, "ShowMyComplexityChanges", 20);
if (!show_my_complexity_changes)
{
return;
}
if (!isAgentAvatarValid() || !gAgentWearables.areWearablesLoaded())
{
// data not ready, nothing to show.
@ -291,7 +297,8 @@ static const char* e_hud_messages[] =
};
LLHUDRenderNotifier::LLHUDRenderNotifier() :
mReportedHUDWarning(WARN_NONE)
mReportedHUDWarning(WARN_NONE),
mHUDsCount(0)
{
}
@ -307,6 +314,15 @@ void LLHUDRenderNotifier::updateNotificationHUD(hud_complexity_list_t complexity
return;
}
mHUDComplexityList = complexity;
mHUDsCount = mHUDComplexityList.size();
static LLCachedControl<U32> show_my_complexity_changes(gSavedSettings, "ShowMyComplexityChanges", 20);
if (!show_my_complexity_changes)
{
return;
}
// TODO:
// Find a way to show message with list of issues, but without making it too large
// and intrusive.

View File

@ -30,6 +30,9 @@
#define LL_llavatarrendernotifier_H
#include "llnotificationptr.h"
#include "llviewerobject.h"
#include "llhudobject.h"
class LLViewerRegion;
@ -63,6 +66,25 @@ struct LLHUDComplexity
typedef std::list<LLHUDComplexity> hud_complexity_list_t;
struct LLObjectComplexity
{
LLObjectComplexity()
{
reset();
}
void reset()
{
objectId = LLUUID::null;
objectName = "";
objectCost = 0;
}
LLUUID objectId;
std::string objectName;
U32 objectCost;
};
typedef std::list<LLObjectComplexity> object_complexity_list_t;
// Class to notify user about drastic changes in agent's render weights or if other agents
// reported that user's agent is too 'heavy' for their settings
class LLAvatarRenderNotifier : public LLSingleton<LLAvatarRenderNotifier>
@ -77,6 +99,9 @@ public:
void updateNotificationState();
void updateNotificationAgent(U32 agentComplexity);
void setObjectComplexityList(object_complexity_list_t object_list) { mObjectComplexityList = object_list; }
object_complexity_list_t getObjectComplexityList() { return mObjectComplexityList; }
private:
LLNotificationPtr mNotificationPtr;
@ -109,6 +134,8 @@ private:
// Used to detect changes in voavatar's rezzed status.
// If value decreases - there were changes in outfit.
S32 mLastOutfitRezStatus;
object_complexity_list_t mObjectComplexityList;
};
// Class to notify user about heavy set of HUD
@ -121,6 +148,9 @@ public:
void updateNotificationHUD(hud_complexity_list_t complexity);
bool isNotificationVisible();
hud_complexity_list_t getHUDComplexityList() { return mHUDComplexityList; }
S32 getHUDsCount() { return mHUDsCount; }
private:
enum EWarnLevel
{
@ -141,6 +171,8 @@ private:
EWarnLevel mReportedHUDWarning;
LLHUDComplexity mLatestHUDComplexity;
LLFrameTimer mHUDPopUpDelayTimer;
hud_complexity_list_t mHUDComplexityList;
S32 mHUDsCount;
};
#endif /* ! defined(LL_llavatarrendernotifier_H) */

View File

@ -80,6 +80,7 @@ void LLControlAvatar::initInstance()
const LLVOAvatar *LLControlAvatar::getAttachedAvatar() const
{
LL_PROFILE_ZONE_SCOPED;
if (mRootVolp && mRootVolp->isAttachment())
{
return mRootVolp->getAvatarAncestor();
@ -89,6 +90,7 @@ const LLVOAvatar *LLControlAvatar::getAttachedAvatar() const
LLVOAvatar *LLControlAvatar::getAttachedAvatar()
{
LL_PROFILE_ZONE_SCOPED;
if (mRootVolp && mRootVolp->isAttachment())
{
return mRootVolp->getAvatarAncestor();

View File

@ -50,6 +50,7 @@
#include "lldrawpoolwlsky.h"
#include "llglslshader.h"
#include "llglcommonfunc.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
S32 LLDrawPool::sNumDrawPools = 0;
@ -388,10 +389,21 @@ void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL t
{
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{}; // <FS:Beq/> Perf stats
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo *pparams = *k;
if (pparams) {
// <FS:Beq> Capture render times
if(pparams->mFace)
{
LLViewerObject* vobj = pparams->mFace->getViewerObject();
if(vobj->isAttachment())
{
trackAttachments( vobj, pparams->mFace->isState(LLFace::RIGGED),&ratPtr);
}
}
// </FS:Beq>
pushBatch(*pparams, mask, texture);
}
}
@ -404,11 +416,22 @@ void LLRenderPass::renderTexture(U32 type, U32 mask, BOOL batch_textures)
void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures)
{
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{};
for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)
{
LLDrawInfo* pparams = *i;
if (pparams)
{
// <FS:Beq> Capture render times
if(pparams->mFace)
{
LLViewerObject* vobj = pparams->mFace->getViewerObject();
if(vobj->isAttachment())
{
trackAttachments( vobj, pparams->mFace->isState(LLFace::RIGGED),&ratPtr);
}
}
// </FS:Beq>
pushBatch(*pparams, mask, texture, batch_textures);
}
}
@ -416,11 +439,22 @@ void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_text
void LLRenderPass::pushMaskBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures)
{
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{};
for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)
{
LLDrawInfo* pparams = *i;
if (pparams)
{
// <FS:Beq> Capture render times
if((*pparams).mFace)
{
LLViewerObject* vobj = (*pparams).mFace->getViewerObject();
if(vobj->isAttachment())
{
trackAttachments( vobj, (*pparams).mFace->isState(LLFace::RIGGED),&ratPtr);
}
}
// </FS:Beq>
if (LLGLSLShader::sCurBoundShaderPtr)
{
LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff);

View File

@ -48,6 +48,7 @@
#include "lldrawpoolwater.h"
#include "llspatialpartition.h"
#include "llglcommonfunc.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE;
@ -341,6 +342,7 @@ void LLDrawPoolAlpha::render(S32 pass)
void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask)
{
LL_PROFILE_ZONE_SCOPED;
for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i)
{
LLSpatialGroup* group = *i;
@ -349,9 +351,20 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask)
{
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA];
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{}; // <FS:Beq/> Render time Stats collection
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo& params = **k;
// <FS:Beq> Capture render times
if(params.mFace)
{
LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
if(vobj->isAttachment())
{
trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr );
}
}
// </FS:Beq>
if (params.mParticle)
{
@ -477,6 +490,7 @@ void LLDrawPoolAlpha::RestoreTexSetup(bool tex_setup)
void LLDrawPoolAlpha::renderSimples(U32 mask, std::vector<LLDrawInfo*>& simples)
{
LL_PROFILE_ZONE_SCOPED;
gPipeline.enableLightsDynamic();
simple_shader->bind();
simple_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep);
@ -485,8 +499,17 @@ void LLDrawPoolAlpha::renderSimples(U32 mask, std::vector<LLDrawInfo*>& simples)
simple_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, 0.0f);
simple_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 0.0f);
bool use_shaders = gPipeline.canUseVertexShaders();
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{};// <FS:Beq> Render time Stats collection
for (LLDrawInfo* draw : simples)
{
// <FS:Beq> Capture render times
LL_PROFILE_ZONE_NAMED("Simples");
auto vobj = draw->mFace?draw->mFace->getViewerObject():nullptr;
if(vobj && vobj->isAttachment())
{
trackAttachments( vobj, draw->mFace->isState(LLFace::RIGGED), &ratPtr );
}
// </FS:Beq>
bool tex_setup = TexSetup(draw, use_shaders, false, simple_shader);
LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test);
gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
@ -503,8 +526,17 @@ void LLDrawPoolAlpha::renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& full
fullbright_shader->bind();
fullbright_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.0f);
bool use_shaders = gPipeline.canUseVertexShaders();
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{}; // <FS:Beq> Render time Stats collection
for (LLDrawInfo* draw : fullbrights)
{
// <FS:Beq> Capture render times
LL_PROFILE_ZONE_NAMED("Fullbrights");
auto vobj = draw->mFace?draw->mFace->getViewerObject():nullptr;
if(vobj && vobj->isAttachment())
{
trackAttachments( vobj, draw->mFace->isState(LLFace::RIGGED), &ratPtr );
}
// </FS:Beq>
bool tex_setup = TexSetup(draw, use_shaders, false, fullbright_shader);
LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test);
@ -518,13 +550,24 @@ void LLDrawPoolAlpha::renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& full
void LLDrawPoolAlpha::renderMaterials(U32 mask, std::vector<LLDrawInfo*>& materials)
{
LL_PROFILE_ZONE_SCOPED;// <FS:Beq> Tracy markup
LLGLSLShader::bindNoShader();
current_shader = NULL;
gPipeline.enableLightsDynamic();
bool use_shaders = gPipeline.canUseVertexShaders();
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{}; // <FS:Beq/> Render time Stats collection
for (LLDrawInfo* draw : materials)
{
// <FS:Beq> Capture render times
LL_PROFILE_ZONE_NAMED("Materials");
auto vobj = draw->mFace?draw->mFace->getViewerObject():nullptr;
if(vobj && vobj->isAttachment())
{
trackAttachments( vobj, draw->mFace->isState(LLFace::RIGGED), &ratPtr );
}
// </FS:Beq>
U32 mask = draw->mShaderMask;
llassert(mask < LLMaterial::SHADER_COUNT);
@ -605,8 +648,18 @@ void LLDrawPoolAlpha::renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissi
// don't touch color, add to alpha (glow)
gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, LLRender::BF_ONE, LLRender::BF_ONE);
bool use_shaders = gPipeline.canUseVertexShaders();
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{}; // <FS:Beq/> Render time Stats collection
for (LLDrawInfo* draw : emissives)
{
// <FS:Beq> Capture render times
LL_PROFILE_ZONE_NAMED("Emissives");
auto vobj = draw->mFace?draw->mFace->getViewerObject():nullptr;
if(vobj && vobj->isAttachment())
{
trackAttachments( vobj, draw->mFace->isState(LLFace::RIGGED), &ratPtr );
}
// </FS:Beq>
bool tex_setup = TexSetup(draw, use_shaders, false, emissive_shader);
drawEmissive(mask, draw);
RestoreTexSetup(tex_setup);
@ -664,6 +717,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA];
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{}; // <FS:Beq/> Render time Stats collection
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo& params = **k;
@ -679,6 +733,18 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
continue;
}
// <FS:Beq> Capture render times
if(params.mFace)
{
LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
if(vobj->isAttachment())
{
trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr );
}
}
// </FS:Beq>
// Fix for bug - NORSPEC-271
// If the face is more than 90% transparent, then don't update the Depth buffer for Dof
// We don't want the nearly invisible objects to cause of DoF effects
@ -858,7 +924,9 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
gGL.matrixMode(LLRender::MM_MODELVIEW);
}
}
// <FS:Beq> performance stats
ratPtr.reset(); // force the final batch to terminate to avoid double counting on the subsidiary batches for FB and Emmissives
// </FS:Beq>
if (batch_fullbrights)
{
light_enabled = false;

View File

@ -59,6 +59,8 @@
// void drawBoxOutline(const LLVector3& pos,const LLVector3& size); // llspatialpartition.cpp
// </FS:Zi>
#include "llnetmap.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK;
static U32 sBufferUsage = GL_STREAM_DRAW_ARB;
@ -605,13 +607,16 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)
{
return;
}
FSPerfStats::RecordAvatarTime T(avatarp->getID(), FSPerfStats::StatType_t::RENDER_SHADOWS);
LLVOAvatar::AvatarOverallAppearance oa = avatarp->getOverallAppearance();
BOOL impostor = !LLPipeline::sImpostorRender && avatarp->isImpostor();
// <FS:Beq> plain old impostors are passing through the shadow pipeline
// if (oa == LLVOAvatar::AOA_INVISIBLE ||
// (impostor && oa == LLVOAvatar::AOA_JELLYDOLL))
// Note: Impostors should not cast shadows, also all JDs are impostor nowadays so we do not need the extra check at all.
if (impostor || (oa == LLVOAvatar::AOA_INVISIBLE) )
// also no shadows if the shadows are causing this avatar to breach the limit.
if ( avatarp->isTooSlowWithShadows() || impostor || (oa == LLVOAvatar::AOA_INVISIBLE) )
// </FS:Beq>
{
// No shadows for jellydolled or invisible avs.
@ -1556,6 +1561,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == -1)
{
LL_PROFILE_ZONE_NAMED("pass -1");
for (S32 i = 1; i < getNumPasses(); i++)
{ //skip foot shadows
prerender();
@ -1572,7 +1578,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
return;
}
LLVOAvatar *avatarp = NULL;
LLVOAvatar *avatarp { nullptr };
if (single_avatar)
{
@ -1580,6 +1586,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
}
else
{
LL_PROFILE_ZONE_NAMED("Find avatarp"); // <FS:Beq/> Tracy markup
const LLFace *facep = mDrawFace[0];
if (!facep->getDrawable())
{
@ -1592,11 +1599,16 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
{
return;
}
FSPerfStats::RecordAvatarTime T(avatarp->getID(), FSPerfStats::StatType_t::RENDER_GEOMETRY);
// <FS:Zi> Add avatar hitbox debug
{
LL_PROFILE_ZONE_NAMED("cached control renderhitboxes");
static LLCachedControl<bool> render_hitbox(gSavedSettings, "DebugRenderHitboxes", false);
if (render_hitbox && pass == 2)
{
LL_PROFILE_ZONE_NAMED("render_hitbox");
LLGLSLShader* current_shader_program = NULL;
// load the debug output shader
@ -1675,10 +1687,14 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
}
}
}
// </FS:Zi>
}// </FS:Zi>
// <FS:Beq> rendertime Tracy annotations
{
LL_PROFILE_ZONE_NAMED("check fully_loaded");
// </FS:Beq>
if (!single_avatar && !avatarp->isFullyLoaded() )
{
LL_PROFILE_ZONE_NAMED("avatar not loaded");
if (pass==0 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0))
{
// debug code to draw a sphere in place of avatar
@ -1701,9 +1717,14 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
// don't render please
return;
}
}// <FS:Beq/> rendertime Tracy annotations
BOOL impostor = !LLPipeline::sImpostorRender && avatarp->isImpostor() && !single_avatar;
// <FS:Beq> rendertime Tracy annotations
{
LL_PROFILE_ZONE_NAMED("check appearance");
// </FS:Beq>
if (( /*avatarp->isInMuteList() // <FS:Ansariel> Partially undo MAINT-5700: Draw imposter for muted avatars
||*/ impostor
|| (LLVOAvatar::AOA_NORMAL != avatarp->getOverallAppearance() && !avatarp->needsImpostorUpdate()) ) && pass != 0)
@ -1711,6 +1732,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
{ //don't draw anything but the impostor for impostored avatars
return;
}
}// <FS:Beq/> rendertime Tracy annotations
if (pass == 0 && !impostor && LLPipeline::sUnderWaterRender)
{ //don't draw foot shadows under water
@ -1726,6 +1748,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == 0)
{
LL_PROFILE_ZONE_NAMED("pass 0");
if (!LLPipeline::sReflectionRender)
{
LLVOAvatar::sNumVisibleAvatars++;
@ -1734,6 +1757,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
// if (impostor || (LLVOAvatar::AV_DO_NOT_RENDER == avatarp->getVisualMuteSettings() && !avatarp->needsImpostorUpdate()))
if (impostor || (LLVOAvatar::AOA_NORMAL != avatarp->getOverallAppearance() && !avatarp->needsImpostorUpdate()))
{
LL_PROFILE_ZONE_NAMED("render impostor");
if (LLPipeline::sRenderDeferred && !LLPipeline::sReflectionRender && avatarp->mImpostor.isComplete())
{
// <FS:Ansariel> FIRE-9179: Crash fix
@ -1759,6 +1783,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == 1)
{
LL_PROFILE_ZONE_NAMED("render rigid meshes (eyeballs)");
// render rigid meshes (eyeballs) first
avatarp->renderRigid();
return;
@ -1766,12 +1791,15 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == 3)
{
LL_PROFILE_ZONE_NAMED("pass 3");
if (is_deferred_render)
{
LL_PROFILE_ZONE_NAMED("deferred rigged simple");
renderDeferredRiggedSimple(avatarp);
}
else
{
LL_PROFILE_ZONE_NAMED("non-deferred rigged");
renderRiggedSimple(avatarp);
if (LLPipeline::sRenderDeferred)
@ -1795,12 +1823,15 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == 4)
{
LL_PROFILE_ZONE_NAMED("pass 4");
if (is_deferred_render)
{
LL_PROFILE_ZONE_NAMED("deferred rigged bump");
renderDeferredRiggedBump(avatarp);
}
else
{
LL_PROFILE_ZONE_NAMED("non-deferred fullbright");
renderRiggedFullbright(avatarp);
}
@ -1809,6 +1840,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (is_deferred_render && pass >= 5 && pass <= 21)
{
LL_PROFILE_ZONE_NAMED("deferred passes 5-21");
S32 p = pass-5;
if (p != 1 &&
@ -1816,6 +1848,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
p != 9 &&
p != 13)
{
LL_PROFILE_ZONE_NAMED("deferred rigged material");
renderDeferredRiggedMaterial(avatarp, p);
}
return;
@ -1826,6 +1859,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == 5)
{
LL_PROFILE_ZONE_NAMED("rigged shiny");
renderRiggedShinySimple(avatarp);
return;
@ -1833,6 +1867,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == 6)
{
LL_PROFILE_ZONE_NAMED("rigged FB shiny");
renderRiggedFullbrightShiny(avatarp);
return;
}
@ -1841,10 +1876,12 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
{
if (pass == 7)
{
LL_PROFILE_ZONE_NAMED("pass 7 rigged Alpha");
renderRiggedAlpha(avatarp);
if (LLPipeline::sRenderDeferred && !is_post_deferred_render)
{ //render transparent materials under water
LL_PROFILE_ZONE_NAMED("rigged Alpha Blend");
LLGLEnable blend(GL_BLEND);
gGL.setColorMask(true, true);
@ -1865,6 +1902,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == 8)
{
LL_PROFILE_ZONE_NAMED("pass 8 rigged FB Alpha");
renderRiggedFullbrightAlpha(avatarp);
return;
}
@ -1881,6 +1919,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
}
{
LL_PROFILE_ZONE_NAMED("post deferred rigged Alpha");
LLGLEnable blend(GL_BLEND);
renderDeferredRiggedMaterial(avatarp, p);
}
@ -1888,6 +1927,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
}
else if (pass == 9)
{
LL_PROFILE_ZONE_NAMED("pass 9 - rigged glow");
renderRiggedGlow(avatarp);
return;
}
@ -1895,6 +1935,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == 13)
{
LL_PROFILE_ZONE_NAMED("pass 13 - rigged glow");
renderRiggedGlow(avatarp);
return;
@ -1902,6 +1943,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if ((sShaderLevel >= SHADER_LEVEL_CLOTH))
{
LL_PROFILE_ZONE_NAMED("shader level > CLOTH");
LLMatrix4 rot_mat;
LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat);
LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
@ -1927,6 +1969,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if( !single_avatar || (avatarp == single_avatar) )
{
LL_PROFILE_ZONE_NAMED("renderSkinned");
avatarp->renderSkinned();
}
}
@ -2328,6 +2371,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
stop_glerror();
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{};// <FS:Beq/> Perf stats capture
for (U32 i = 0; i < mRiggedFace[type].size(); ++i)
{
LLFace* face = mRiggedFace[type][i];
@ -2350,7 +2394,14 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
{
continue;
}
// <FS:Beq> Capture render times
if(vobj->isAttachment())
{
trackAttachments( vobj, true, &ratPtr);
}
// </FS:Beq>
LLVolume* volume = vobj->getVolume();
S32 te = face->getTEOffset();
@ -2651,11 +2702,15 @@ static LLTrace::BlockTimerStatHandle FTM_RIGGED_VBO("Rigged VBO");
void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar)
{
LL_RECORD_BLOCK_TIME(FTM_RIGGED_VBO);
// <FS:Beq> render stats collection
if(!avatar)return; // in theory this never happens...right
FSPerfStats::RecordAvatarTime T( avatar->getID(), ( (LLPipeline::sShadowRender)?FSPerfStats::StatType_t::RENDER_SHADOWS : FSPerfStats::StatType_t::RENDER_GEOMETRY ) );
// </FS:Beq>
//update rigged vertex buffers
for (U32 type = 0; type < NUM_RIGGED_PASSES; ++type)
{
LL_PROFILE_ZONE_NAMED("Pass");
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{};
for (U32 i = 0; i < mRiggedFace[type].size(); ++i)
{
LL_PROFILE_ZONE_NAMED("Face");
@ -2672,7 +2727,12 @@ void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar)
{
continue;
}
// <FS:Beq> Capture render times
if(vobj->isAttachment())
{
trackAttachments( vobj, true, &ratPtr );
}
// </FS:Beq>
LLVolume* volume = vobj->getVolume();
S32 te = face->getTEOffset();

View File

@ -47,6 +47,7 @@
#include "pipeline.h"
#include "llspatialpartition.h"
#include "llviewershadermgr.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
//#include "llimagebmp.h"
//#include "../tools/imdebug/imdebug.h"
@ -640,13 +641,22 @@ void LLDrawPoolBump::endFullbrightShiny()
}
void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE)
{
{
LL_PROFILE_ZONE_SCOPED;
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{}; // <FS:Beq/> render time capture
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo& params = **k;
// <FS:Beq> Capture render times
LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
if( vobj && vobj->isAttachment() )
{
trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr );
}
// </FS:Beq>
applyModelMatrix(params);
if (params.mGroup)
@ -888,10 +898,21 @@ void LLDrawPoolBump::renderDeferred(S32 pass)
U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR;
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{}; // <FS:Beq/> render time capture
for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)
{
LLDrawInfo& params = **i;
// <FS:Beq> Capture render times
if(params.mFace)
{
LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
if(vobj && vobj->isAttachment())
{
trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr );
}
}
// </FS:Beq>
gDeferredBumpProgram.setMinimumAlpha(params.mAlphaMaskCutoff);
LLDrawPoolBump::bindBumpMap(params, bump_channel);
pushBatch(params, mask, TRUE);
@ -1499,9 +1520,21 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask)
LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{}; // <FS:Beq/> render time capture
for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)
{
LLDrawInfo& params = **i;
// <FS:Beq> Capture render times
if(params.mFace)
{
LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
if( vobj && vobj->isAttachment() )
{
trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr );
}
}
// </FS:Beq>
if (LLDrawPoolBump::bindBumpMap(params))
{
@ -1512,6 +1545,7 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask)
void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
{
LL_PROFILE_ZONE_SCOPED;
applyModelMatrix(params);
bool tex_setup = false;

View File

@ -31,6 +31,7 @@
#include "llviewershadermgr.h"
#include "pipeline.h"
#include "llglcommonfunc.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
S32 diffuse_channel = -1;
@ -135,10 +136,23 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass)
LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{}; // <FS:Beq/> render time capture
for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)
{
LLDrawInfo& params = **i;
// <FS:Beq> Capture render times
if(params.mFace)
{
LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
if( vobj && vobj->isAttachment() )
{
trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr );
}
}
// </FS:Beq>
mShader->uniform4f(LLShaderMgr::SPECULAR_COLOR, params.mSpecColor.mV[0], params.mSpecColor.mV[1], params.mSpecColor.mV[2], params.mSpecColor.mV[3]);
mShader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, params.mEnvIntensity);

View File

@ -36,6 +36,7 @@
#include "llspatialpartition.h"
#include "llviewershadermgr.h"
#include "llrender.h"
#include "fsperfstats.h"
static LLGLSLShader* simple_shader = NULL;
static LLGLSLShader* fullbright_shader = NULL;
@ -224,7 +225,7 @@ void LLDrawPoolSimple::render(S32 pass)
LLGLDisable blend(GL_BLEND);
{ //render simple
LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE);
LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE);
gPipeline.enableLightsDynamic();
if (mShaderLevel > 0)

View File

@ -228,12 +228,15 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
BOOL ret = FALSE ;
for( S32 order = 0; order < ORDER_COUNT; order++ )
{
LL_PROFILE_ZONE_SCOPED;
for (instance_list_t::iterator iter = LLViewerDynamicTexture::sInstances[order].begin();
iter != LLViewerDynamicTexture::sInstances[order].end(); ++iter)
{
LL_PROFILE_ZONE_SCOPED;
LLViewerDynamicTexture *dynamicTexture = *iter;
if (dynamicTexture->needsRender())
{
{
LL_PROFILE_ZONE_NAMED("needsRender");
glClear(GL_DEPTH_BUFFER_BIT);
gDepthDirty = TRUE;
@ -241,13 +244,19 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
dynamicTexture->setBoundTarget(use_fbo ? &gPipeline.mBake : nullptr);
dynamicTexture->preRender(); // Must be called outside of startRender()
result = FALSE;
{
LL_PROFILE_ZONE_NAMED("DynTexture->render");
if (dynamicTexture->render())
{
ret = TRUE ;
result = TRUE;
sNumRenders++;
}
}
{
LL_PROFILE_ZONE_NAMED("flush");
gGL.flush();
}
LLVertexBuffer::unbind();
dynamicTexture->setBoundTarget(nullptr);
dynamicTexture->postRender(result);

View File

@ -59,6 +59,7 @@
// [RLVa:KB] - Checked: RLVa-2.0.0
#include "rlvhandler.h"
// [/RLVa:KB]
#include "fsperfstats.h" // <FS:Beq> performance stats support
#if LL_LINUX
// Work-around spurious used before init warning on Vector4a
@ -651,6 +652,13 @@ void renderFace(LLDrawable* drawable, LLFace *face)
LLVOVolume* vobj = drawable->getVOVolume();
if (vobj)
{
// <FS:Beq> Placeholder - This function emits drawcalls but is only used in one place and not useful for stats.
// TODO(Beq) if we need this consider moving it to llSelectMgr loop instead to reduce overhead.
// std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{};
// if(vobj->isAttachment())
// {
// trackAttachments(vobj, LLPipeline::sShadowRender, &ratPtr);
// }
LLVolume* volume = NULL;
if (drawable->isState(LLDrawable::RIGGED))
@ -1251,6 +1259,11 @@ bool LLFace::canRenderAsMask()
{
return false;
}
// <FS:Beq> shortcircuit fully alpha faces
if (getViewerObject()->isHUDAttachment()) { return false; }
if (te->getAlpha() == 0.0f && (te->getGlow() == 0.f)) { LL_PROFILE_ZONE_NAMED("beqshortcircuit invisible"); return true; }
// </FS:Beq>
LLMaterial* mat = te->getMaterialParams();
if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND)

View File

@ -64,6 +64,7 @@
#include "llnotificationhandler.h"
#include "llnotificationmanager.h"
#include "llnotificationsutil.h"
#include "llviewercontrol.h"
LLFloaterAutoReplaceSettings::LLFloaterAutoReplaceSettings(const LLSD& key)

View File

@ -91,7 +91,6 @@ BOOL LLFloaterAvatarRenderSettings::postBuild()
LLFloater::postBuild();
mAvatarSettingsList = getChild<LLNameListCtrl>("render_settings_list");
mAvatarSettingsList->setRightMouseDownCallback(boost::bind(&LLFloaterAvatarRenderSettings::onAvatarListRightClick, this, _1, _2, _3));
getChild<LLFilterEditor>("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterAvatarRenderSettings::onFilterEdit, this, _2));
return TRUE;
}
@ -135,37 +134,13 @@ void LLFloaterAvatarRenderSettings::updateList()
{
item_params.value = iter->first;
LLAvatarNameCache::get(iter->first, &av_name);
if(!isHiddenRow(av_name.getCompleteName()))
{
item_params.columns.add().value(av_name.getCompleteName()).column("name");
std::string setting = getString(iter->second == 1 ? "av_never_render" : "av_always_render");
item_params.columns.add().value(setting).column("setting");
std::string timestamp = createTimestamp(LLRenderMuteList::getInstance()->getVisualMuteDate(iter->first));
item_params.columns.add().value(timestamp).column("timestamp");
mAvatarSettingsList->addNameItemRow(item_params);
}
item_params.columns.add().value(av_name.getCompleteName()).column("name");
std::string setting = getString(iter->second == 1 ? "av_never_render" : "av_always_render");
item_params.columns.add().value(setting).column("setting");
mAvatarSettingsList->addNameItemRow(item_params);
}
}
void LLFloaterAvatarRenderSettings::onFilterEdit(const std::string& search_string)
{
std::string filter_upper = search_string;
LLStringUtil::toUpper(filter_upper);
if (mNameFilter != filter_upper)
{
mNameFilter = filter_upper;
mNeedsUpdate = true;
}
}
bool LLFloaterAvatarRenderSettings::isHiddenRow(const std::string& av_name)
{
if (mNameFilter.empty()) return false;
std::string upper_name = av_name;
LLStringUtil::toUpper(upper_name);
return std::string::npos == upper_name.find(mNameFilter);
}
static LLVOAvatar* find_avatar(const LLUUID& id)
{
LLViewerObject *obj = gObjectList.findObject(id);
@ -216,6 +191,10 @@ bool LLFloaterAvatarRenderSettings::isActionChecked(const LLSD& userdata, const
{
return (visual_setting == S32(LLVOAvatar::AV_RENDER_NORMALLY));
}
else if ("non_default" == command_name)
{
return (visual_setting != S32(LLVOAvatar::AV_RENDER_NORMALLY));
}
else if ("never" == command_name)
{
return (visual_setting == S32(LLVOAvatar::AV_DO_NOT_RENDER));

View File

@ -50,7 +50,6 @@ public:
void onAvatarListRightClick(LLUICtrl* ctrl, S32 x, S32 y);
void updateList();
void onFilterEdit(const std::string& search_string);
void onCustomAction (const LLSD& userdata, const LLUUID& av_id);
bool isActionChecked(const LLSD& userdata, const LLUUID& av_id);
void onClickAdd(const LLSD& userdata);
@ -61,15 +60,12 @@ public:
static void setNeedsUpdate();
private:
bool isHiddenRow(const std::string& av_name);
void callbackAvatarPicked(const uuid_vec_t& ids, S32 visual_setting);
void removePicker();
bool mNeedsUpdate;
LLListContextMenu* mContextMenu;
LLNameListCtrl* mAvatarSettingsList;
std::string mNameFilter;
};

View File

@ -53,6 +53,7 @@
#include "llfloaterreg.h"
#include "llfloaterabout.h"
#include "llfavoritesbar.h"
#include "llfloaterpreferencesgraphicsadvanced.h"
#include "llfloatersidepanelcontainer.h"
// <FS:Ansariel> [FS communication UI]
//#include "llfloaterimsession.h"
@ -84,7 +85,6 @@
#include "llviewereventrecorder.h"
#include "llviewermessage.h"
#include "llviewerwindow.h"
#include "llviewershadermgr.h"
#include "llviewerthrottle.h"
#include "llvoavatarself.h"
#include "llvotree.h"
@ -108,11 +108,9 @@
#include "lltextbox.h"
#include "llui.h"
#include "llviewerobjectlist.h"
#include "llvoavatar.h"
#include "llvovolume.h"
#include "llwindow.h"
#include "llworld.h"
#include "pipeline.h"
#include "lluictrlfactory.h"
#include "llviewermedia.h"
#include "llpluginclassmedia.h"
@ -128,8 +126,6 @@
#include "llpresetsmanager.h"
#include "llviewercontrol.h"
#include "llpresetsmanager.h"
#include "llfeaturemanager.h"
#include "llviewertexturelist.h"
#include "llsearchableui.h"
@ -143,18 +139,19 @@
#include "llaudioengine.h" // <FS:Ansariel> Output device selection
#include "llavatarname.h" // <FS:CR> Deeper name cache stuffs
#include "llclipboard.h" // <FS:Zi> Support preferences search SLURLs
#include "lleventtimer.h"
#include "llviewermenufile.h" // <FS:LO> FIRE-23606 Reveal path to external script editor in prefernces
#include "lldiriterator.h" // <Kadah> for populating the fonts combo
#include "lleventtimer.h"
#include "llline.h"
#include "lllocationhistory.h"
#include "llpanelblockedlist.h"
#include "llpanelmaininventory.h"
#include "llscrolllistctrl.h"
#include "llspellcheck.h"
#include "llsdserialize.h" // KB: SkinsSelector
#include "llspellcheck.h"
#include "lltoolbarview.h"
#include "llviewermenufile.h" // <FS:LO> FIRE-23606 Reveal path to external script editor in prefernces
#include "llviewernetwork.h" // <FS:AW opensim search support>
#include "llviewershadermgr.h"
#include "NACLantispam.h"
#include "../llcrashlogger/llcrashlogger.h"
#if LL_WINDOWS
@ -168,9 +165,11 @@
#endif
// </FS:LO>
#include "fsperfstats.h"// <FS:Beq/> perfstats
// <FS:Zi> FIRE-19539 - Include the alert messages in Prefs>Notifications>Alerts in preference Search.
#include "llfiltereditor.h"
#include "llviewershadermgr.h"
//<FS:HG> FIRE-6340, FIRE-6567 - Setting Bandwidth issues
//const F32 BANDWIDTH_UPDATER_TIMEOUT = 0.5f;
char const* const VISIBILITY_DEFAULT = "default";
@ -507,6 +506,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this );
mComplexityChangedSignal = gSavedSettings.getControl("RenderAvatarMaxComplexity")->getCommitSignal()->connect(boost::bind(&LLFloaterPreference::updateComplexityText, this));
mCommitCallbackRegistrar.add("Pref.ClearLog", boost::bind(&LLConversationLog::onClearLog, &LLConversationLog::instance()));
mCommitCallbackRegistrar.add("Pref.DeleteTranscripts", boost::bind(&LLFloaterPreference::onDeleteTranscripts, this));
mCommitCallbackRegistrar.add("UpdateFilter", boost::bind(&LLFloaterPreference::onUpdateFilterTerm, this, false)); // <FS:ND/> Hook up for filtering
@ -892,6 +893,7 @@ void LLFloaterPreference::onDoNotDisturbResponseChanged()
LLFloaterPreference::~LLFloaterPreference()
{
LLConversationLog::instance().removeObserver(this);
mComplexityChangedSignal.disconnect();
}
// <FS:Zi> FIRE-19539 - Include the alert messages in Prefs>Notifications>Alerts in preference Search.
@ -1276,33 +1278,6 @@ void LLFloaterPreference::onRenderOptionEnable()
refreshEnabledGraphics();
}
void LLFloaterPreferenceGraphicsAdvanced::onRenderOptionEnable()
{
LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
if (instance)
{
instance->refresh();
}
refreshEnabledGraphics();
}
void LLFloaterPreferenceGraphicsAdvanced::onAdvancedAtmosphericsEnable()
{
LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
if (instance)
{
instance->refresh();
}
refreshEnabledGraphics();
}
void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledGraphics()
{
refreshEnabledState();
}
void LLFloaterPreference::onAvatarImpostorsEnable()
{
refreshEnabledGraphics();
@ -2325,129 +2300,6 @@ void LLFloaterPreference::onCopySearch()
}
// </FS:Zi>
void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
{
LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections");
LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText");
// Reflections
BOOL reflections = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps;
ctrl_reflections->setEnabled(reflections);
reflections_text->setEnabled(reflections);
// Transparent Water
LLCheckBoxCtrl* transparent_water_ctrl = getChild<LLCheckBoxCtrl>("TransparentWater");
// Bump & Shiny
LLCheckBoxCtrl* bumpshiny_ctrl = getChild<LLCheckBoxCtrl>("BumpShiny");
bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump");
bumpshiny_ctrl->setEnabled(bumpshiny ? TRUE : FALSE);
// Avatar Mode
// Enable Avatar Shaders
LLCheckBoxCtrl* ctrl_avatar_vp = getChild<LLCheckBoxCtrl>("AvatarVertexProgram");
// Avatar Render Mode
LLCheckBoxCtrl* ctrl_avatar_cloth = getChild<LLCheckBoxCtrl>("AvatarCloth");
bool avatar_vp_enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP");
if (LLViewerShaderMgr::sInitialized)
{
S32 max_avatar_shader = LLViewerShaderMgr::instance()->mMaxAvatarShaderLevel;
avatar_vp_enabled = (max_avatar_shader > 0) ? TRUE : FALSE;
}
ctrl_avatar_vp->setEnabled(avatar_vp_enabled);
if (gSavedSettings.getBOOL("RenderAvatarVP") == FALSE)
{
ctrl_avatar_cloth->setEnabled(FALSE);
}
else
{
ctrl_avatar_cloth->setEnabled(TRUE);
}
/* <FS:LO> remove orphaned code left over from EEP
// Vertex Shaders, Global Shader Enable
// SL-12594 Basic shaders are always enabled. DJH TODO clean up now-orphaned state handling code
LLSliderCtrl* terrain_detail = getChild<LLSliderCtrl>("TerrainDetail"); // can be linked with control var
LLTextBox* terrain_text = getChild<LLTextBox>("TerrainDetailText");
terrain_detail->setEnabled(FALSE);
terrain_text->setEnabled(FALSE);
*/
// WindLight
LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail");
LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText");
// [RLVa:KB] - Checked: 2010-03-18 (RLVa-1.2.0a) | Modified: RLVa-0.2.0a
// "Atmospheric Shaders" can't be disabled - but can be enabled - under @setenv=n
ctrl_wind_light->setEnabled( (RlvActions::canChangeEnvironment()) || (!gSavedSettings.getBOOL("WindLightUseAtmosShaders")));
// [/RLVa:KB]
// ctrl_wind_light->setEnabled(TRUE);
sky->setEnabled(TRUE);
sky_text->setEnabled(TRUE);
//Deferred/SSAO/Shadows
LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
((bumpshiny_ctrl && bumpshiny_ctrl->get()) ? TRUE : FALSE) &&
((transparent_water_ctrl && transparent_water_ctrl->get()) ? TRUE : FALSE) &&
gGLManager.mHasFramebufferObject &&
gSavedSettings.getBOOL("RenderAvatarVP") &&
(ctrl_wind_light->get()) ? TRUE : FALSE;
ctrl_deferred->setEnabled(enabled);
LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");
LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF");
LLComboBox* ctrl_shadow = getChild<LLComboBox>("ShadowDetail");
LLTextBox* shadow_text = getChild<LLTextBox>("RenderShadowDetailText");
// note, okay here to get from ctrl_deferred as it's twin, ctrl_deferred2 will alway match it
enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO") && (ctrl_deferred->get() ? TRUE : FALSE);
ctrl_deferred->set(gSavedSettings.getBOOL("RenderDeferred"));
ctrl_ssao->setEnabled(enabled);
ctrl_dof->setEnabled(enabled);
enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail");
ctrl_shadow->setEnabled(enabled);
shadow_text->setEnabled(enabled);
// Hardware settings
F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple");
S32Megabytes min_tex_mem = LLViewerTextureList::getMinVideoRamSetting();
S32Megabytes max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(false, mem_multiplier);
getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMinValue(min_tex_mem.value());
getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMaxValue(max_tex_mem.value());
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
!gGLManager.mHasVertexBufferObject)
{
getChildView("vbo")->setEnabled(FALSE);
}
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderCompressTextures") ||
!gGLManager.mHasVertexBufferObject)
{
getChildView("texture compression")->setEnabled(FALSE);
}
// if no windlight shaders, turn off nighttime brightness, gamma, and fog distance
LLUICtrl* gamma_ctrl = getChild<LLUICtrl>("gamma");
gamma_ctrl->setEnabled(!gPipeline.canUseWindLightShaders());
getChildView("(brightness, lower is brighter)")->setEnabled(!gPipeline.canUseWindLightShaders());
getChildView("fog")->setEnabled(!gPipeline.canUseWindLightShaders());
getChildView("antialiasing restart")->setVisible(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"));
// now turn off any features that are unavailable
disableUnavailableSettings();
}
// static
void LLAvatarComplexityControls::setIndirectControls()
@ -2594,118 +2446,6 @@ void LLFloaterPreference::disableUnavailableSettings()
}
}
void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings()
{
LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections");
LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText");
LLCheckBoxCtrl* ctrl_avatar_vp = getChild<LLCheckBoxCtrl>("AvatarVertexProgram");
LLCheckBoxCtrl* ctrl_avatar_cloth = getChild<LLCheckBoxCtrl>("AvatarCloth");
LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
LLComboBox* ctrl_shadows = getChild<LLComboBox>("ShadowDetail");
LLTextBox* shadows_text = getChild<LLTextBox>("RenderShadowDetailText");
LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");
LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF");
LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail");
LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText");
// disabled windlight
if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"))
{
ctrl_wind_light->setEnabled(FALSE);
ctrl_wind_light->setValue(FALSE);
sky->setEnabled(FALSE);
sky_text->setEnabled(FALSE);
//deferred needs windlight, disable deferred
ctrl_shadows->setEnabled(FALSE);
ctrl_shadows->setValue(0);
shadows_text->setEnabled(FALSE);
ctrl_ssao->setEnabled(FALSE);
ctrl_ssao->setValue(FALSE);
ctrl_dof->setEnabled(FALSE);
ctrl_dof->setValue(FALSE);
ctrl_deferred->setEnabled(FALSE);
ctrl_deferred->setValue(FALSE);
}
// disabled deferred
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") ||
!gGLManager.mHasFramebufferObject)
{
ctrl_shadows->setEnabled(FALSE);
ctrl_shadows->setValue(0);
shadows_text->setEnabled(FALSE);
ctrl_ssao->setEnabled(FALSE);
ctrl_ssao->setValue(FALSE);
ctrl_dof->setEnabled(FALSE);
ctrl_dof->setValue(FALSE);
ctrl_deferred->setEnabled(FALSE);
ctrl_deferred->setValue(FALSE);
}
// disabled deferred SSAO
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO"))
{
ctrl_ssao->setEnabled(FALSE);
ctrl_ssao->setValue(FALSE);
}
// disabled deferred shadows
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail"))
{
ctrl_shadows->setEnabled(FALSE);
ctrl_shadows->setValue(0);
shadows_text->setEnabled(FALSE);
}
// disabled reflections
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionDetail"))
{
ctrl_reflections->setEnabled(FALSE);
ctrl_reflections->setValue(FALSE);
reflections_text->setEnabled(FALSE);
}
// disabled av
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP"))
{
ctrl_avatar_vp->setEnabled(FALSE);
ctrl_avatar_vp->setValue(FALSE);
ctrl_avatar_cloth->setEnabled(FALSE);
ctrl_avatar_cloth->setValue(FALSE);
//deferred needs AvatarVP, disable deferred
ctrl_shadows->setEnabled(FALSE);
ctrl_shadows->setValue(0);
shadows_text->setEnabled(FALSE);
ctrl_ssao->setEnabled(FALSE);
ctrl_ssao->setValue(FALSE);
ctrl_dof->setEnabled(FALSE);
ctrl_dof->setValue(FALSE);
ctrl_deferred->setEnabled(FALSE);
ctrl_deferred->setValue(FALSE);
}
// disabled cloth
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth"))
{
ctrl_avatar_cloth->setEnabled(FALSE);
ctrl_avatar_cloth->setValue(FALSE);
}
}
void LLFloaterPreference::refresh()
{
LLPanel::refresh();
@ -2730,32 +2470,6 @@ void LLFloaterPreference::refresh()
updateClickActionViews();
}
void LLFloaterPreferenceGraphicsAdvanced::refresh()
{
getChild<LLUICtrl>("fsaa")->setValue((LLSD::Integer) gSavedSettings.getU32("RenderFSAASamples"));
// sliders and their text boxes
// mPostProcess = gSavedSettings.getS32("RenderGlowResolutionPow");
// slider text boxes
updateSliderText(getChild<LLSliderCtrl>("ObjectMeshDetail", true), getChild<LLTextBox>("ObjectMeshDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("FlexibleMeshDetail", true), getChild<LLTextBox>("FlexibleMeshDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("TreeMeshDetail", true), getChild<LLTextBox>("TreeMeshDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("AvatarMeshDetail", true), getChild<LLTextBox>("AvatarMeshDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("AvatarPhysicsDetail", true), getChild<LLTextBox>("AvatarPhysicsDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("TerrainMeshDetail", true), getChild<LLTextBox>("TerrainMeshDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("RenderPostProcess", true), getChild<LLTextBox>("PostProcessText", true));
updateSliderText(getChild<LLSliderCtrl>("SkyMeshDetail", true), getChild<LLTextBox>("SkyMeshDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("TerrainDetail", true), getChild<LLTextBox>("TerrainDetailText", true));
LLAvatarComplexityControls::setIndirectControls();
setMaxNonImpostorsText(
gSavedSettings.getU32("RenderAvatarMaxNonImpostors"),
getChild<LLTextBox>("IndirectMaxNonImpostorsText", true));
LLAvatarComplexityControls::setText(
gSavedSettings.getU32("RenderAvatarMaxComplexity"),
getChild<LLTextBox>("IndirectMaxComplexityText", true));
refreshEnabledState();
}
void LLFloaterPreference::onCommitWindowedMode()
{
refresh();
@ -3119,64 +2833,7 @@ void LLFloaterPreference::updateMaxComplexityLabel(const LLSD& newvalue)
}
// </FS:Ansariel>
void LLFloaterPreferenceGraphicsAdvanced::updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box)
{
if (text_box == NULL || ctrl== NULL)
return;
// get range and points when text should change
F32 value = (F32)ctrl->getValue().asReal();
F32 min = ctrl->getMinValue();
F32 max = ctrl->getMaxValue();
F32 range = max - min;
llassert(range > 0);
F32 midPoint = min + range / 3.0f;
F32 highPoint = min + (2.0f * range / 3.0f);
// choose the right text
if (value < midPoint)
{
text_box->setText(LLTrans::getString("GraphicsQualityLow"));
}
else if (value < highPoint)
{
text_box->setText(LLTrans::getString("GraphicsQualityMid"));
}
else
{
text_box->setText(LLTrans::getString("GraphicsQualityHigh"));
}
}
void LLFloaterPreferenceGraphicsAdvanced::updateMaxNonImpostors()
{
// Called when the IndirectMaxNonImpostors control changes
// Responsible for fixing the slider label (IndirectMaxNonImpostorsText) and setting RenderAvatarMaxNonImpostors
LLSliderCtrl* ctrl = getChild<LLSliderCtrl>("IndirectMaxNonImpostors",true);
U32 value = ctrl->getValue().asInteger();
if (0 == value || LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER <= value)
{
value=0;
}
gSavedSettings.setU32("RenderAvatarMaxNonImpostors", value);
LLVOAvatar::updateImpostorRendering(value); // make it effective immediately
setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText"));
}
void LLFloaterPreferenceGraphicsAdvanced::setMaxNonImpostorsText(U32 value, LLTextBox* text_box)
{
if (0 == value)
{
text_box->setText(LLTrans::getString("no_limit"));
}
else
{
text_box->setText(llformat("%d", value));
}
}
void LLAvatarComplexityControls::updateMax(LLSliderCtrl* slider, LLTextBox* value_label)
void LLAvatarComplexityControls::updateMax(LLSliderCtrl* slider, LLTextBox* value_label, bool short_val)
{
// Called when the IndirectMaxComplexity control changes
// Responsible for fixing the slider label (IndirectMaxComplexityText) and setting RenderAvatarMaxComplexity
@ -3198,10 +2855,10 @@ void LLAvatarComplexityControls::updateMax(LLSliderCtrl* slider, LLTextBox* valu
}
gSavedSettings.setU32("RenderAvatarMaxComplexity", (U32)max_arc);
setText(max_arc, value_label);
setText(max_arc, value_label, short_val);
}
void LLAvatarComplexityControls::setText(U32 value, LLTextBox* text_box)
void LLAvatarComplexityControls::setText(U32 value, LLTextBox* text_box, bool short_val)
{
if (0 == value)
{
@ -3210,28 +2867,45 @@ void LLAvatarComplexityControls::setText(U32 value, LLTextBox* text_box)
else
{
// <FS:Ansariel> Proper number formatting with delimiter
//text_box->setText(llformat("%d", value));
//std::string text_value = short_val ? llformat("%d", value / 1000) : llformat("%d", value);
//text_box->setText(text_value);
std::string output_string;
LLLocale locale("");
LLResMgr::getInstance()->getIntegerString(output_string, value);
LLResMgr::getInstance()->getIntegerString(output_string, (short_val ? value / 1000 : value));
text_box->setText(output_string);
}
}
// <FS:Beq> redner time controls
void LLAvatarComplexityControls::updateMaxRenderTime(LLSliderCtrl* slider, LLTextBox* value_label, bool short_val)
{
setRenderTimeText((F32)(FSPerfStats::renderAvatarMaxART_ns/1000), value_label, short_val);
}
void LLAvatarComplexityControls::setRenderTimeText(F32 value, LLTextBox* text_box, bool short_val)
{
if (0 == value)
{
text_box->setText(LLTrans::getString("no_limit"));
}
else
{
text_box->setText(llformat("%.0f", value));
}
}
// </FS:Beq>
void LLFloaterPreference::updateMaxComplexity()
{
// Called when the IndirectMaxComplexity control changes
LLAvatarComplexityControls::updateMax(
getChild<LLSliderCtrl>("IndirectMaxComplexity"),
getChild<LLTextBox>("IndirectMaxComplexityText"));
}
LLFloaterPreferenceGraphicsAdvanced* floater_graphics_advanced = LLFloaterReg::findTypedInstance<LLFloaterPreferenceGraphicsAdvanced>("prefs_graphics_advanced");
if (floater_graphics_advanced)
{
LLAvatarComplexityControls::updateMax(
floater_graphics_advanced->getChild<LLSliderCtrl>("IndirectMaxComplexity"),
floater_graphics_advanced->getChild<LLTextBox>("IndirectMaxComplexityText"));
}
void LLFloaterPreference::updateComplexityText()
{
LLAvatarComplexityControls::setText(gSavedSettings.getU32("RenderAvatarMaxComplexity"),
getChild<LLTextBox>("IndirectMaxComplexityText", true));
}
bool LLFloaterPreference::loadFromFilename(const std::string& filename, std::map<std::string, std::string> &label_map)
@ -3273,22 +2947,6 @@ bool LLFloaterPreference::loadFromFilename(const std::string& filename, std::map
return true;
}
void LLFloaterPreferenceGraphicsAdvanced::updateMaxComplexity()
{
// Called when the IndirectMaxComplexity control changes
LLAvatarComplexityControls::updateMax(
getChild<LLSliderCtrl>("IndirectMaxComplexity"),
getChild<LLTextBox>("IndirectMaxComplexityText"));
LLFloaterPreference* floater_preferences = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
if (floater_preferences)
{
LLAvatarComplexityControls::updateMax(
floater_preferences->getChild<LLSliderCtrl>("IndirectMaxComplexity"),
floater_preferences->getChild<LLTextBox>("IndirectMaxComplexityText"));
}
}
void LLFloaterPreference::onChangeMaturity()
{
U8 sim_access = gSavedSettings.getU32("PreferredMaturity");
@ -5050,18 +4708,6 @@ void LLPanelPreferenceControls::onCancelKeyBind()
pControlsTable->deselectAllItems();
}
LLFloaterPreferenceGraphicsAdvanced::LLFloaterPreferenceGraphicsAdvanced(const LLSD& key)
: LLFloater(key)
{
mCommitCallbackRegistrar.add("Pref.RenderOptionUpdate", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::onRenderOptionEnable, this));
mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxNonImpostors", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateMaxNonImpostors,this));
mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxComplexity", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateMaxComplexity,this));
}
LLFloaterPreferenceGraphicsAdvanced::~LLFloaterPreferenceGraphicsAdvanced()
{
}
LLFloaterPreferenceProxy::LLFloaterPreferenceProxy(const LLSD& key)
: LLFloater(key),
mSocksSettingsDirty(false)
@ -5071,41 +4717,6 @@ LLFloaterPreferenceProxy::LLFloaterPreferenceProxy(const LLSD& key)
mCommitCallbackRegistrar.add("Proxy.Change", boost::bind(&LLFloaterPreferenceProxy::onChangeSocksSettings, this));
}
BOOL LLFloaterPreferenceGraphicsAdvanced::postBuild()
{
// Don't do this on Mac as their braindead GL versioning
// sets this when 8x and 16x are indeed available
//
#if !LL_DARWIN
if (gGLManager.mIsIntel || gGLManager.mGLVersion < 3.f)
{ //remove FSAA settings above "4x"
LLComboBox* combo = getChild<LLComboBox>("fsaa");
combo->remove("8x");
combo->remove("16x");
}
LLCheckBoxCtrl *use_HiDPI = getChild<LLCheckBoxCtrl>("use HiDPI");
use_HiDPI->setVisible(FALSE);
#endif
return TRUE;
}
void LLFloaterPreferenceGraphicsAdvanced::onOpen(const LLSD& key)
{
refresh();
}
void LLFloaterPreferenceGraphicsAdvanced::onClickCloseBtn(bool app_quitting)
{
LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
if (instance)
{
instance->cancel();
}
updateMaxComplexity();
}
LLFloaterPreferenceProxy::~LLFloaterPreferenceProxy()
{
}

View File

@ -120,12 +120,10 @@ public:
// updates click/double-click action controls depending on values from settings.xml
void updateClickActionViews();
// <FS:CR> Make onBtnOk() public for settings backup panel
//protected:
void onBtnOK(const LLSD& userdata);
protected:
// </FS:CR>
void onBtnCancel(const LLSD& userdata);
void onBtnOK(const LLSD& userdata);
void onBtnCancel(const LLSD& userdata);
protected:
//void onClickClearCache(); // Clear viewer texture cache, file cache on next startup // AO: was protected, moved to public
void onClickBrowserClearCache(); // Clear web history and caches as well as viewer caches above
@ -301,6 +299,7 @@ private:
void onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response);
void updateDeleteTranscriptsButton();
void updateMaxComplexity();
void updateComplexityText();
static bool loadFromFilename(const std::string& filename, std::map<std::string, std::string> &label_map);
static std::string sSkin;
@ -321,6 +320,8 @@ private:
LLSearchEditor *mFilterEdit;
std::unique_ptr< ll::prefs::SearchData > mSearchData;
boost::signals2::connection mComplexityChangedSignal;
void onUpdateFilterTerm( bool force = false );
void collectSearchableItems();
@ -473,37 +474,15 @@ private:
S32 mEditingMode;
};
class LLFloaterPreferenceGraphicsAdvanced : public LLFloater
{
public:
LLFloaterPreferenceGraphicsAdvanced(const LLSD& key);
~LLFloaterPreferenceGraphicsAdvanced();
/*virtual*/ BOOL postBuild();
void onOpen(const LLSD& key);
void onClickCloseBtn(bool app_quitting);
void disableUnavailableSettings();
void refreshEnabledGraphics();
void refreshEnabledState();
void updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box);
void updateMaxNonImpostors();
void setMaxNonImpostorsText(U32 value, LLTextBox* text_box);
void updateMaxComplexity();
void setMaxComplexityText(U32 value, LLTextBox* text_box);
static void setIndirectControls();
static void setIndirectMaxNonImpostors();
static void setIndirectMaxArc();
void refresh();
// callback for when client modifies a render option
void onRenderOptionEnable();
void onAdvancedAtmosphericsEnable();
LOG_CLASS(LLFloaterPreferenceGraphicsAdvanced);
};
class LLAvatarComplexityControls
{
public:
static void updateMax(LLSliderCtrl* slider, LLTextBox* value_label);
static void setText(U32 value, LLTextBox* text_box);
static void updateMax(LLSliderCtrl* slider, LLTextBox* value_label, bool short_val = false);
static void setText(U32 value, LLTextBox* text_box, bool short_val = false);
// <FS:Beq> for render time support
static void updateMaxRenderTime(LLSliderCtrl* slider, LLTextBox* value_label, bool short_val = false);
static void setRenderTimeText(F32 value, LLTextBox* text_box, bool short_val = false);
// </FS:Beq>
static void setIndirectControls();
static void setIndirectMaxNonImpostors();
static void setIndirectMaxArc();

View File

@ -0,0 +1,474 @@
/**
* @file llfloaterpreferencesgraphicsadvanced.cpp
* @brief floater for adjusting camera position
*
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2021, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloaterpreferencesgraphicsadvanced.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "llfeaturemanager.h"
#include "llfloaterpreference.h"
#include "llfloaterreg.h"
#include "llsliderctrl.h"
#include "lltextbox.h"
#include "lltrans.h"
#include "llviewershadermgr.h"
#include "llviewertexturelist.h"
#include "llvoavatar.h"
#include "pipeline.h"
#include "llviewercontrol.h"
#include "rlvactions.h"
LLFloaterPreferenceGraphicsAdvanced::LLFloaterPreferenceGraphicsAdvanced(const LLSD& key)
: LLFloater(key)
{
mCommitCallbackRegistrar.add("Pref.RenderOptionUpdate", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::onRenderOptionEnable, this));
mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxNonImpostors", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateMaxNonImpostors,this));
mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxComplexity", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateMaxComplexity,this));
mCommitCallbackRegistrar.add("Pref.Cancel", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::onBtnCancel, this, _2));
mCommitCallbackRegistrar.add("Pref.OK", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::onBtnOK, this, _2));
}
LLFloaterPreferenceGraphicsAdvanced::~LLFloaterPreferenceGraphicsAdvanced()
{
mComplexityChangedSignal.disconnect();
}
BOOL LLFloaterPreferenceGraphicsAdvanced::postBuild()
{
// Don't do this on Mac as their braindead GL versioning
// sets this when 8x and 16x are indeed available
//
#if !LL_DARWIN
if (gGLManager.mIsIntel || gGLManager.mGLVersion < 3.f)
{ //remove FSAA settings above "4x"
LLComboBox* combo = getChild<LLComboBox>("fsaa");
combo->remove("8x");
combo->remove("16x");
}
LLCheckBoxCtrl *use_HiDPI = getChild<LLCheckBoxCtrl>("use HiDPI");
use_HiDPI->setVisible(FALSE);
#endif
mComplexityChangedSignal = gSavedSettings.getControl("RenderAvatarMaxComplexity")->getCommitSignal()->connect(boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateComplexityText, this));
return TRUE;
}
void LLFloaterPreferenceGraphicsAdvanced::onOpen(const LLSD& key)
{
refresh();
}
void LLFloaterPreferenceGraphicsAdvanced::onClickCloseBtn(bool app_quitting)
{
LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
if (instance)
{
instance->cancel();
}
updateMaxComplexity();
}
void LLFloaterPreferenceGraphicsAdvanced::onRenderOptionEnable()
{
LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
if (instance)
{
instance->refresh();
}
refreshEnabledGraphics();
}
void LLFloaterPreferenceGraphicsAdvanced::onAdvancedAtmosphericsEnable()
{
LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
if (instance)
{
instance->refresh();
}
refreshEnabledGraphics();
}
void LLFloaterPreferenceGraphicsAdvanced::refresh()
{
getChild<LLUICtrl>("fsaa")->setValue((LLSD::Integer) gSavedSettings.getU32("RenderFSAASamples"));
// sliders and their text boxes
// mPostProcess = gSavedSettings.getS32("RenderGlowResolutionPow");
// slider text boxes
updateSliderText(getChild<LLSliderCtrl>("ObjectMeshDetail", true), getChild<LLTextBox>("ObjectMeshDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("FlexibleMeshDetail", true), getChild<LLTextBox>("FlexibleMeshDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("TreeMeshDetail", true), getChild<LLTextBox>("TreeMeshDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("AvatarMeshDetail", true), getChild<LLTextBox>("AvatarMeshDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("AvatarPhysicsDetail", true), getChild<LLTextBox>("AvatarPhysicsDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("TerrainMeshDetail", true), getChild<LLTextBox>("TerrainMeshDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("RenderPostProcess", true), getChild<LLTextBox>("PostProcessText", true));
updateSliderText(getChild<LLSliderCtrl>("SkyMeshDetail", true), getChild<LLTextBox>("SkyMeshDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("TerrainDetail", true), getChild<LLTextBox>("TerrainDetailText", true));
LLAvatarComplexityControls::setIndirectControls();
setMaxNonImpostorsText(
gSavedSettings.getU32("RenderAvatarMaxNonImpostors"),
getChild<LLTextBox>("IndirectMaxNonImpostorsText", true));
LLAvatarComplexityControls::setText(
gSavedSettings.getU32("RenderAvatarMaxComplexity"),
getChild<LLTextBox>("IndirectMaxComplexityText", true));
refreshEnabledState();
}
void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledGraphics()
{
refreshEnabledState();
}
void LLFloaterPreferenceGraphicsAdvanced::updateMaxComplexity()
{
// Called when the IndirectMaxComplexity control changes
LLAvatarComplexityControls::updateMax(
getChild<LLSliderCtrl>("IndirectMaxComplexity"),
getChild<LLTextBox>("IndirectMaxComplexityText"));
}
void LLFloaterPreferenceGraphicsAdvanced::updateComplexityText()
{
LLAvatarComplexityControls::setText(gSavedSettings.getU32("RenderAvatarMaxComplexity"),
getChild<LLTextBox>("IndirectMaxComplexityText", true));
}
void LLFloaterPreferenceGraphicsAdvanced::updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box)
{
if (text_box == NULL || ctrl== NULL)
return;
// get range and points when text should change
F32 value = (F32)ctrl->getValue().asReal();
F32 min = ctrl->getMinValue();
F32 max = ctrl->getMaxValue();
F32 range = max - min;
llassert(range > 0);
F32 midPoint = min + range / 3.0f;
F32 highPoint = min + (2.0f * range / 3.0f);
// choose the right text
if (value < midPoint)
{
text_box->setText(LLTrans::getString("GraphicsQualityLow"));
}
else if (value < highPoint)
{
text_box->setText(LLTrans::getString("GraphicsQualityMid"));
}
else
{
text_box->setText(LLTrans::getString("GraphicsQualityHigh"));
}
}
void LLFloaterPreferenceGraphicsAdvanced::updateMaxNonImpostors()
{
// Called when the IndirectMaxNonImpostors control changes
// Responsible for fixing the slider label (IndirectMaxNonImpostorsText) and setting RenderAvatarMaxNonImpostors
LLSliderCtrl* ctrl = getChild<LLSliderCtrl>("IndirectMaxNonImpostors",true);
U32 value = ctrl->getValue().asInteger();
if (0 == value || LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER <= value)
{
value=0;
}
gSavedSettings.setU32("RenderAvatarMaxNonImpostors", value);
LLVOAvatar::updateImpostorRendering(value); // make it effective immediately
setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText"));
}
void LLFloaterPreferenceGraphicsAdvanced::setMaxNonImpostorsText(U32 value, LLTextBox* text_box)
{
if (0 == value)
{
text_box->setText(LLTrans::getString("no_limit"));
}
else
{
text_box->setText(llformat("%d", value));
}
}
void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings()
{
LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections");
LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText");
LLCheckBoxCtrl* ctrl_avatar_vp = getChild<LLCheckBoxCtrl>("AvatarVertexProgram");
LLCheckBoxCtrl* ctrl_avatar_cloth = getChild<LLCheckBoxCtrl>("AvatarCloth");
LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
LLComboBox* ctrl_shadows = getChild<LLComboBox>("ShadowDetail");
LLTextBox* shadows_text = getChild<LLTextBox>("RenderShadowDetailText");
LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");
LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF");
LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail");
LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText");
// disabled windlight
if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"))
{
ctrl_wind_light->setEnabled(FALSE);
ctrl_wind_light->setValue(FALSE);
sky->setEnabled(FALSE);
sky_text->setEnabled(FALSE);
//deferred needs windlight, disable deferred
ctrl_shadows->setEnabled(FALSE);
ctrl_shadows->setValue(0);
shadows_text->setEnabled(FALSE);
ctrl_ssao->setEnabled(FALSE);
ctrl_ssao->setValue(FALSE);
ctrl_dof->setEnabled(FALSE);
ctrl_dof->setValue(FALSE);
ctrl_deferred->setEnabled(FALSE);
ctrl_deferred->setValue(FALSE);
}
// disabled deferred
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") ||
!gGLManager.mHasFramebufferObject)
{
ctrl_shadows->setEnabled(FALSE);
ctrl_shadows->setValue(0);
shadows_text->setEnabled(FALSE);
ctrl_ssao->setEnabled(FALSE);
ctrl_ssao->setValue(FALSE);
ctrl_dof->setEnabled(FALSE);
ctrl_dof->setValue(FALSE);
ctrl_deferred->setEnabled(FALSE);
ctrl_deferred->setValue(FALSE);
}
// disabled deferred SSAO
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO"))
{
ctrl_ssao->setEnabled(FALSE);
ctrl_ssao->setValue(FALSE);
}
// disabled deferred shadows
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail"))
{
ctrl_shadows->setEnabled(FALSE);
ctrl_shadows->setValue(0);
shadows_text->setEnabled(FALSE);
}
// disabled reflections
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionDetail"))
{
ctrl_reflections->setEnabled(FALSE);
ctrl_reflections->setValue(FALSE);
reflections_text->setEnabled(FALSE);
}
// disabled av
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP"))
{
ctrl_avatar_vp->setEnabled(FALSE);
ctrl_avatar_vp->setValue(FALSE);
ctrl_avatar_cloth->setEnabled(FALSE);
ctrl_avatar_cloth->setValue(FALSE);
//deferred needs AvatarVP, disable deferred
ctrl_shadows->setEnabled(FALSE);
ctrl_shadows->setValue(0);
shadows_text->setEnabled(FALSE);
ctrl_ssao->setEnabled(FALSE);
ctrl_ssao->setValue(FALSE);
ctrl_dof->setEnabled(FALSE);
ctrl_dof->setValue(FALSE);
ctrl_deferred->setEnabled(FALSE);
ctrl_deferred->setValue(FALSE);
}
// disabled cloth
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth"))
{
ctrl_avatar_cloth->setEnabled(FALSE);
ctrl_avatar_cloth->setValue(FALSE);
}
}
void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
{
LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections");
LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText");
// Reflections
BOOL reflections = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps;
ctrl_reflections->setEnabled(reflections);
reflections_text->setEnabled(reflections);
// Transparent Water
LLCheckBoxCtrl* transparent_water_ctrl = getChild<LLCheckBoxCtrl>("TransparentWater");
// Bump & Shiny
LLCheckBoxCtrl* bumpshiny_ctrl = getChild<LLCheckBoxCtrl>("BumpShiny");
bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump");
bumpshiny_ctrl->setEnabled(bumpshiny ? TRUE : FALSE);
// Avatar Mode
// Enable Avatar Shaders
LLCheckBoxCtrl* ctrl_avatar_vp = getChild<LLCheckBoxCtrl>("AvatarVertexProgram");
// Avatar Render Mode
LLCheckBoxCtrl* ctrl_avatar_cloth = getChild<LLCheckBoxCtrl>("AvatarCloth");
bool avatar_vp_enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP");
if (LLViewerShaderMgr::sInitialized)
{
S32 max_avatar_shader = LLViewerShaderMgr::instance()->mMaxAvatarShaderLevel;
avatar_vp_enabled = (max_avatar_shader > 0) ? TRUE : FALSE;
}
ctrl_avatar_vp->setEnabled(avatar_vp_enabled);
if (gSavedSettings.getBOOL("RenderAvatarVP") == FALSE)
{
ctrl_avatar_cloth->setEnabled(FALSE);
}
else
{
ctrl_avatar_cloth->setEnabled(TRUE);
}
/* <FS:LO> remove orphaned code left over from EEP
// Vertex Shaders, Global Shader Enable
// SL-12594 Basic shaders are always enabled. DJH TODO clean up now-orphaned state handling code
LLSliderCtrl* terrain_detail = getChild<LLSliderCtrl>("TerrainDetail"); // can be linked with control var
LLTextBox* terrain_text = getChild<LLTextBox>("TerrainDetailText");
terrain_detail->setEnabled(FALSE);
terrain_text->setEnabled(FALSE);
*/
// WindLight
LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail");
LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText");
// [RLVa:KB] - Checked: 2010-03-18 (RLVa-1.2.0a) | Modified: RLVa-0.2.0a
// "Atmospheric Shaders" can't be disabled - but can be enabled - under @setenv=n
ctrl_wind_light->setEnabled((RlvActions::canChangeEnvironment()) || (!gSavedSettings.getBOOL("WindLightUseAtmosShaders")));
// [/RLVa:KB]
// ctrl_wind_light->setEnabled(TRUE);
sky->setEnabled(TRUE);
sky_text->setEnabled(TRUE);
//Deferred/SSAO/Shadows
LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
((bumpshiny_ctrl && bumpshiny_ctrl->get()) ? TRUE : FALSE) &&
((transparent_water_ctrl && transparent_water_ctrl->get()) ? TRUE : FALSE) &&
gGLManager.mHasFramebufferObject &&
gSavedSettings.getBOOL("RenderAvatarVP") &&
(ctrl_wind_light->get()) ? TRUE : FALSE;
ctrl_deferred->setEnabled(enabled);
LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");
LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF");
LLComboBox* ctrl_shadow = getChild<LLComboBox>("ShadowDetail");
LLTextBox* shadow_text = getChild<LLTextBox>("RenderShadowDetailText");
// note, okay here to get from ctrl_deferred as it's twin, ctrl_deferred2 will alway match it
enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO") && (ctrl_deferred->get() ? TRUE : FALSE);
ctrl_deferred->set(gSavedSettings.getBOOL("RenderDeferred"));
ctrl_ssao->setEnabled(enabled);
ctrl_dof->setEnabled(enabled);
enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail");
ctrl_shadow->setEnabled(enabled);
shadow_text->setEnabled(enabled);
// Hardware settings
F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple");
S32Megabytes min_tex_mem = LLViewerTextureList::getMinVideoRamSetting();
S32Megabytes max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(false, mem_multiplier);
getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMinValue(min_tex_mem.value());
getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMaxValue(max_tex_mem.value());
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
!gGLManager.mHasVertexBufferObject)
{
getChildView("vbo")->setEnabled(FALSE);
}
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderCompressTextures") ||
!gGLManager.mHasVertexBufferObject)
{
getChildView("texture compression")->setEnabled(FALSE);
}
// if no windlight shaders, turn off nighttime brightness, gamma, and fog distance
LLUICtrl* gamma_ctrl = getChild<LLUICtrl>("gamma");
gamma_ctrl->setEnabled(!gPipeline.canUseWindLightShaders());
getChildView("(brightness, lower is brighter)")->setEnabled(!gPipeline.canUseWindLightShaders());
getChildView("fog")->setEnabled(!gPipeline.canUseWindLightShaders());
getChildView("antialiasing restart")->setVisible(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"));
// now turn off any features that are unavailable
disableUnavailableSettings();
}
void LLFloaterPreferenceGraphicsAdvanced::onBtnOK(const LLSD& userdata)
{
LLFloaterPreference* instance = LLFloaterReg::getTypedInstance<LLFloaterPreference>("preferences");
if (instance)
{
instance->onBtnOK(userdata);
}
}
void LLFloaterPreferenceGraphicsAdvanced::onBtnCancel(const LLSD& userdata)
{
LLFloaterPreference* instance = LLFloaterReg::getTypedInstance<LLFloaterPreference>("preferences");
if (instance)
{
instance->onBtnCancel(userdata);
}
}

View File

@ -0,0 +1,65 @@
/**
* @file llfloaterpreferencesgraphicsadvanced.h
*
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2021, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LLFLOATERPREFERENCEGRAPHICSADVANCED_H
#define LLFLOATERPREFERENCEGRAPHICSADVANCED_H
#include "llcontrol.h"
#include "llfloater.h"
class LLSliderCtrl;
class LLTextBox;
class LLFloaterPreferenceGraphicsAdvanced : public LLFloater
{
public:
LLFloaterPreferenceGraphicsAdvanced(const LLSD& key);
~LLFloaterPreferenceGraphicsAdvanced();
/*virtual*/ BOOL postBuild();
void onOpen(const LLSD& key);
void onClickCloseBtn(bool app_quitting);
void disableUnavailableSettings();
void refreshEnabledGraphics();
void refreshEnabledState();
void updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box);
void updateMaxNonImpostors();
void setMaxNonImpostorsText(U32 value, LLTextBox* text_box);
void updateMaxComplexity();
void updateComplexityText();
void refresh();
// callback for when client modifies a render option
void onRenderOptionEnable();
void onAdvancedAtmosphericsEnable();
LOG_CLASS(LLFloaterPreferenceGraphicsAdvanced);
protected:
void onBtnOK(const LLSD& userdata);
void onBtnCancel(const LLSD& userdata);
boost::signals2::connection mComplexityChangedSignal;
};
#endif //LLFLOATERPREFERENCEGRAPHICSADVANCED_H

View File

@ -71,9 +71,11 @@ LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p)
mNameColumnIndex(p.name_column.column_index),
mNameColumn(p.name_column.column_name),
mAllowCallingCardDrop(p.allow_calling_card_drop),
mShortNames(p.short_names)
mShortNames(p.short_names),
// <FS:Ansariel> Fix Baker's NameListCtrl un-fix
//mPendingLookupsRemaining(0)
//mPendingLookupsRemaining(0),
mHoverIconName("Info_Small"),
mNameListType(INDIVIDUAL)
{}
// public
@ -140,7 +142,12 @@ BOOL LLNameListCtrl::handleDragAndDrop(
void LLNameListCtrl::showInspector(const LLUUID& avatar_id, bool is_group, bool is_experience)
{
if(is_experience)
if (isSpecialType())
{
mIconClickedSignal(avatar_id);
return;
}
if(is_experience)
{
LLFloaterReg::showInstance("experience_profile", avatar_id, true);
return;
@ -224,14 +231,16 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask)
S32 column_index = getColumnIndexFromOffset(x);
LLNameListItem* hit_item = dynamic_cast<LLNameListItem*>(hitItem(x, y));
LLFloater* floater = gFloaterView->getParentFloater(this);
if (floater
if (floater
&& floater->isFrontmost()
&& hit_item
&& column_index == mNameColumnIndex)
&& ((column_index == mNameColumnIndex) || isSpecialType()))
{
// ...this is the column with the avatar name
LLUUID avatar_id = hit_item->getUUID();
if (avatar_id.notNull())
// ...this is the column with the avatar name
LLUUID item_id = isSpecialType() ? hit_item->getSpecialID() : hit_item->getUUID();
if (item_id.notNull())
{
// ...valid avatar id
@ -239,13 +248,13 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask)
if (hit_cell)
{
S32 row_index = getItemIndex(hit_item);
LLRect cell_rect = getCellRect(row_index, column_index);
LLRect cell_rect = getCellRect(row_index, isSpecialType() ? getNumColumns() - 1 : column_index);
// Convert rect local to screen coordinates
LLRect sticky_rect;
localRectToScreen(cell_rect, &sticky_rect);
// Spawn at right side of cell
LLPointer<LLUIImage> icon = LLUI::getUIImage("Info_Small");
LLPointer<LLUIImage> icon = LLUI::getUIImage(mHoverIconName);
S32 screenX = sticky_rect.mRight - info_icon_size;
S32 screenY = sticky_rect.mTop - (sticky_rect.getHeight() - icon->getHeight()) / 2;
LLCoordGL pos(screenX, screenY);
@ -259,7 +268,7 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask)
LLToolTip::Params params;
params.background_visible(false);
params.click_callback(boost::bind(&LLNameListCtrl::showInspector, this, avatar_id, is_group, is_experience));
params.click_callback(boost::bind(&LLNameListCtrl::showInspector, this, item_id, is_group, is_experience));
params.delay_time(0.0f); // spawn instantly on hover
params.image(icon);
params.message("");
@ -336,6 +345,7 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(
// use supplied name by default
std::string fullname = name_item.name;
switch(name_item.target)
{
case GROUP:
@ -354,8 +364,10 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(
}
break;
case SPECIAL:
// just use supplied name
break;
{
item->setSpecialID(name_item.special_id());
return item;
}
case INDIVIDUAL:
{
LLAvatarName av_name;
@ -366,7 +378,7 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(
else if (LLAvatarNameCache::get(id, &av_name))
{
if (mShortNames)
fullname = av_name.getDisplayName();
fullname = av_name.getDisplayName(true);
else
fullname = av_name.getCompleteName();
}
@ -437,7 +449,8 @@ void LLNameListCtrl::removeNameItem(const LLUUID& agent_id)
for (item_list::iterator it = getItemList().begin(); it != getItemList().end(); it++)
{
LLScrollListItem* item = *it;
if (item->getUUID() == agent_id)
LLUUID cur_id = isSpecialType() ? dynamic_cast<LLNameListItem*>(item)->getSpecialID() : item->getUUID();
if (cur_id == agent_id)
{
idx = getItemIndex(item);
break;
@ -469,6 +482,34 @@ LLScrollListItem* LLNameListCtrl::getNameItemByAgentId(const LLUUID& agent_id)
return NULL;
}
void LLNameListCtrl::selectItemBySpecialId(const LLUUID& special_id)
{
if (special_id.isNull())
{
return;
}
for (item_list::iterator it = getItemList().begin(); it != getItemList().end(); it++)
{
LLNameListItem* item = dynamic_cast<LLNameListItem*>(*it);
if (item && item->getSpecialID() == special_id)
{
item->setSelected(TRUE);
break;
}
}
}
LLUUID LLNameListCtrl::getSelectedSpecialId()
{
LLNameListItem* item = dynamic_cast<LLNameListItem*>(getFirstSelected());
if(item)
{
return item->getSpecialID();
}
return LLUUID();
}
void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id,
const LLAvatarName& av_name,
std::string suffix,

View File

@ -52,6 +52,8 @@ public:
void setIsGroup(bool is_group) { mIsGroup = is_group; }
bool isExperience() const { return mIsExperience; }
void setIsExperience(bool is_experience) { mIsExperience = is_experience; }
void setSpecialID(const LLUUID& special_id) { mSpecialID = special_id; }
const LLUUID& getSpecialID() const { return mSpecialID; }
protected:
friend class LLNameListCtrl;
@ -74,6 +76,8 @@ protected:
private:
bool mIsGroup;
bool mIsExperience;
LLUUID mSpecialID;
};
@ -104,10 +108,12 @@ public:
{
Optional<std::string> name;
Optional<ENameType, NameTypeNames> target;
Optional<LLUUID> special_id;
NameItem()
: name("name"),
target("target", INDIVIDUAL)
target("target", INDIVIDUAL),
special_id("special_id", LLUUID())
{}
};
@ -168,6 +174,9 @@ public:
LLScrollListItem* getNameItemByAgentId(const LLUUID& agent_id);
void selectItemBySpecialId(const LLUUID& special_id);
LLUUID getSelectedSpecialId();
// LLView interface
/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
@ -182,6 +191,12 @@ public:
/*virtual*/ void updateColumns(bool force_update);
/*virtual*/ void mouseOverHighlightNthItem( S32 index );
bool isSpecialType() { return (mNameListType == SPECIAL); }
void setNameListType(e_name_type type) { mNameListType = type; }
void setHoverIconName(std::string icon_name) { mHoverIconName = icon_name; }
private:
void showInspector(const LLUUID& avatar_id, bool is_group, bool is_experience = false);
void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, std::string suffix, std::string prefix, LLHandle<LLNameListItem> item);
@ -196,17 +211,28 @@ private:
avatar_name_cache_connection_map_t mAvatarNameCacheConnections;
avatar_name_cache_connection_map_t mGroupNameCacheConnections;
// <FS:Ansariel> Fix Baker's NameListCtrl un-fix
// S32 mPendingLookupsRemaining;
// namelist_complete_signal_t mNameListCompleteSignal;
//
//public:
// boost::signals2::connection setOnNameListCompleteCallback(boost::function<void(bool)> onNameListCompleteCallback)
// {
// return mNameListCompleteSignal.connect(onNameListCompleteCallback);
// }
// </FS:Ansariel>
// <FS:Ansariel> Fix Baker's NameListCtrl un-fix
//S32 mPendingLookupsRemaining;
//namelist_complete_signal_t mNameListCompleteSignal;
// </FS:Ansariel>
std::string mHoverIconName;
e_name_type mNameListType;
boost::signals2::signal<void(const LLUUID &)> mIconClickedSignal;
public:
// <FS:Ansariel> Fix Baker's NameListCtrl un-fix
//boost::signals2::connection setOnNameListCompleteCallback(boost::function<void(bool)> onNameListCompleteCallback)
//{
// return mNameListCompleteSignal.connect(onNameListCompleteCallback);
//}
// </FS:Ansariel>
boost::signals2::connection setIconClickedCallback(boost::function<void(const LLUUID &)> cb)
{
return mIconClickedSignal.connect(cb);
}
};

View File

@ -42,6 +42,7 @@
#include "llagentcamera.h"
#include "llfile.h"
#include "quickprefs.h"
#include "fsperfstats.h" // <FS:Beq/> avoid triggering reloads while autotuning
LLPresetsManager::LLPresetsManager()
// <FS:Ansariel> Graphic preset controls independent from XUI
@ -708,7 +709,9 @@ void LLPresetsManager::handleGraphicPresetControlChanged(LLControlVariablePtr co
{
LL_DEBUGS() << "Handling graphic preset control change: control = " << control->getName() << " - new = " << new_value << " - old = " << old_value << LL_ENDL;
if (!mIsLoadingPreset && (!mIsDrawDistanceSteppingActive || control->getName() != "RenderFarClip"))
if (!mIsLoadingPreset &&
(!mIsDrawDistanceSteppingActive || control->getName() != "RenderFarClip") &&
(!FSPerfStats::autoTune) )
{
LL_DEBUGS() << "Trigger graphic preset control changed signal" << LL_ENDL;

View File

@ -1142,6 +1142,7 @@ public:
virtual S32 frustumCheck(const LLViewerOctreeGroup* group)
{
LL_PROFILE_ZONE_SCOPED;
S32 res = AABBInFrustumNoFarClipGroupBounds(group);
if (res != 0)
{
@ -1152,6 +1153,7 @@ public:
virtual S32 frustumCheckObjects(const LLViewerOctreeGroup* group)
{
LL_PROFILE_ZONE_SCOPED;
S32 res = AABBInFrustumNoFarClipObjectBounds(group);
if (res != 0)
{
@ -1162,6 +1164,7 @@ public:
virtual void processGroup(LLViewerOctreeGroup* base_group)
{
LL_PROFILE_ZONE_SCOPED;
LLSpatialGroup* group = (LLSpatialGroup*)base_group;
if (group->needsUpdate() ||
group->getVisible(LLViewerCamera::sCurCameraID) < LLDrawable::getCurrentFrame() - 1)

View File

@ -210,7 +210,7 @@
#include "llenvironment.h"
#include "llstacktrace.h"
#include "fsperfstats.h"
#if LL_WINDOWS
#include "lldxhardware.h"
#endif
@ -2155,6 +2155,10 @@ bool idle_startup()
update_static_eyes();
// </FS:KC>
// <FS:Beq>
gAgent.addRegionChangedCallback(boost::bind(&FSPerfStats::StatsRecorder::clearStats));
// </FS:Beq>
// *Note: this is where gWorldMap used to be initialized.
// register null callbacks for audio until the audio system is initialized
@ -4257,6 +4261,10 @@ bool process_login_success_response(U32 &first_sim_size_x, U32 &first_sim_size_y
// unpack login data needed by the application
text = response["agent_id"].asString();
if(!text.empty()) gAgentID.set(text);
// <FS:Beq> Performance floater initialisation
FSPerfStats::StatsRecorder::setEnabled(gSavedSettings.getBOOL("FSPerfStatsCaptureEnabled"));
FSPerfStats::StatsRecorder::setFocusAv(gAgentID);
// </FS:Beq>
// gDebugInfo["AgentID"] = text;
// [SL:KB] - Patch: Viewer-CrashReporting | Checked: 2010-11-16 (Catznip-2.6.0a) | Added: Catznip-2.4.0b
if (gCrashSettings.getBOOL("CrashSubmitName"))

View File

@ -587,10 +587,10 @@ void LLStatusBar::refresh()
// <FS:Ansariel> FIRE-14482: Show FPS in status bar
static LLCachedControl<bool> fsStatusBarShowFPS(gSavedSettings, "FSStatusBarShowFPS");
if (fsStatusBarShowFPS && mFPSUpdateTimer.getElapsedTimeF32() > 0.5f)
if (fsStatusBarShowFPS && mFPSUpdateTimer.getElapsedTimeF32() > 1.f)
{
mFPSUpdateTimer.reset();
mFPSText->setText(llformat("%.1f", LLTrace::get_frame_recording().getPeriodMeanPerSec(LLStatViewer::FPS)));
mFPSText->setText(llformat("%.1f", LLTrace::get_frame_recording().getPeriodMedianPerSec(LLStatViewer::FPS)));
}
// </FS:Ansariel>

View File

@ -107,7 +107,7 @@
#include "llviewerregion.h"
#include "NACLantispam.h"
#include "nd/ndlogthrottle.h"
#include "fsperfstats.h"
// <FS:Zi> Run Prio 0 default bento pose in the background to fix splayed hands, open mouths, etc.
#include "llanimationstates.h"
@ -1059,6 +1059,40 @@ void handleDiskCacheSizeChanged(const LLSD& newValue)
}
// </FS:Ansariel>
// <FS:Beq> perrf floater stuffs
void handleTargetFPSChanged(const LLSD& newValue)
{
const auto targetFPS = gSavedSettings.getU32("FSTargetFPS");
FSPerfStats::targetFPS = targetFPS;
}
// <FS:Beq> perrf floater stuffs
void handleAutoTuneFPSChanged(const LLSD& newValue)
{
const auto newval = gSavedSettings.getBOOL("FSAutoTuneFPS");
FSPerfStats::autoTune = newval;
if(newval && FSPerfStats::renderAvatarMaxART_ns == 0) // If we've enabled autotune we override "unlimited" to max
{
gSavedSettings.setF32("FSRenderAvatarMaxART",log10(FSPerfStats::ART_UNLIMITED_NANOS-1000));//triggers callback to update static var
}
}
void handleRenderAvatarMaxARTChanged(const LLSD& newValue)
{
FSPerfStats::StatsRecorder::updateRenderCostLimitFromSettings();
}
void handleFPSTuningStrategyChanged(const LLSD& newValue)
{
const auto newval = gSavedSettings.getU32("FSTuningFPSStrategy");
FSPerfStats::fpsTuningStrategy = newval;
}
void handlePerformanceStatsEnabledChanged(const LLSD& newValue)
{
const auto newval = gSavedSettings.getBOOL("FSPerfStatsCaptureEnabled");
FSPerfStats::StatsRecorder::setEnabled(newval);
}
// </FS:Beq>
////////////////////////////////////////////////////////////////////////////
void settings_setup_listeners()
@ -1313,6 +1347,14 @@ void settings_setup_listeners()
// <FS:Ansariel> Better asset cache size control
gSavedSettings.getControl("FSDiskCacheSize")->getSignal()->connect(boost::bind(&handleDiskCacheSizeChanged, _2));
// <FS:Beq> perf floater controls
gSavedSettings.getControl("FSTargetFPS")->getSignal()->connect(boost::bind(&handleTargetFPSChanged, _2));
gSavedSettings.getControl("FSAutoTuneFPS")->getSignal()->connect(boost::bind(&handleAutoTuneFPSChanged, _2));
gSavedSettings.getControl("FSRenderAvatarMaxART")->getSignal()->connect(boost::bind(&handleRenderAvatarMaxARTChanged, _2));
gSavedSettings.getControl("FSTuningFPSStrategy")->getSignal()->connect(boost::bind(&handleFPSTuningStrategyChanged, _2));
gSavedSettings.getControl("FSPerfStatsCaptureEnabled")->getSignal()->connect(boost::bind(&handlePerformanceStatsEnabledChanged, _2));
// </FS:Beq>
}
#if TEST_CACHED_CONTROL

View File

@ -85,6 +85,7 @@
// [/RLVa:KB]
#include "llpresetsmanager.h"
#include "fsdata.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
extern LLPointer<LLViewerTexture> gStartTexture;
extern bool gShiftFrame;
@ -280,6 +281,7 @@ static LLTrace::BlockTimerStatHandle FTM_EEP_UPDATE("Env Update");
// Paint the display!
void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
{
FSPerfStats::RecordSceneTime T (FSPerfStats::StatType_t::RENDER_DISPLAY); // <FS:Beq/> render time capture - This is the main stat for overall rendering.
LL_RECORD_BLOCK_TIME(FTM_RENDER);
LLViewerCamera& camera = LLViewerCamera::instance(); // <FS:Ansariel> Factor out calls to getInstance
@ -1192,6 +1194,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
void render_hud_attachments()
{
FSPerfStats::RecordSceneTime T ( FSPerfStats::StatType_t::RENDER_HUDS); // <FS:Beq/> render time capture - Primary contributor to HUDs (though these end up in render batches)
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.pushMatrix();
gGL.matrixMode(LLRender::MM_MODELVIEW);
@ -1399,6 +1402,7 @@ bool setup_hud_matrices(const LLRect& screen_region)
void render_ui(F32 zoom_factor, int subfield)
{
FSPerfStats::RecordSceneTime T ( FSPerfStats::StatType_t::RENDER_UI ); // <FS:Beq/> render time capture - Primary UI stat can have HUD time overlap (TODO)
LL_RECORD_BLOCK_TIME(FTM_RENDER_UI);
LLGLState::checkStates();
@ -1492,6 +1496,7 @@ static LLTrace::BlockTimerStatHandle FTM_SWAP("Swap");
void swap()
{
FSPerfStats::RecordSceneTime T ( FSPerfStats::StatType_t::RENDER_SWAP ); // <FS:Beq/> render time capture - Swap buffer time - can signify excessive data transfer to/from GPU
LL_RECORD_BLOCK_TIME(FTM_SWAP);
if (gDisplaySwapBuffers)

View File

@ -105,9 +105,12 @@
#include "llfloaterpathfindingconsole.h"
#include "llfloaterpathfindinglinksets.h"
#include "llfloaterpay.h"
// #include "llfloaterperformance.h" <FS:Beq/> rename to fs as ll version no released
#include "fsfloaterperformance.h"
#include "llfloaterperms.h"
#include "llfloaterpostprocess.h"
#include "llfloaterpreference.h"
#include "llfloaterpreferencesgraphicsadvanced.h"
#include "llfloaterpreferenceviewadvanced.h"
#include "llfloaterpreviewtrash.h"
#include "llfloaterproperties.h"
@ -379,10 +382,11 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("pathfinding_linksets", "floater_pathfinding_linksets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPathfindingLinksets>);
LLFloaterReg::add("pathfinding_console", "floater_pathfinding_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPathfindingConsole>);
LLFloaterReg::add("people", "floater_people.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);
//LLFloaterReg::add("performance", "floater_performance.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPerformance>);
LLFloaterReg::add("perms_default", "floater_perms_default.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPermsDefault>);
LLFloaterReg::add("places", "floater_places.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);
LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>);
LLFloaterReg::add("prefs_graphics_advanced", "floater_preferences_graphics_advanced.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceGraphicsAdvanced>);
// LLFloaterReg::add("prefs_graphics_advanced", "floater_preferences_graphics_advanced.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceGraphicsAdvanced>);
LLFloaterReg::add("prefs_view_advanced", "floater_preferences_view_advanced.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceViewAdvanced>);
LLFloaterReg::add("prefs_proxy", "floater_preferences_proxy.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceProxy>);
LLFloaterReg::add("prefs_spellchecker_import", "floater_spellcheck_import.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSpellCheckerImport>);
@ -500,6 +504,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("media_lists", "floater_media_lists.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FloaterMediaLists>);
LLFloaterReg::add("money_tracker", "floater_fs_money_tracker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSMoneyTracker>);
LLFloaterReg::add("particle_editor","floater_particle_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<ParticleEditor>);
LLFloaterReg::add("performance", "floater_performance.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSFloaterPerformance>);
LLFloaterReg::add(PHOTOTOOLS_FLOATER, "floater_phototools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FloaterQuickPrefs>);
LLFloaterReg::add("phototools_camera", "floater_phototools_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>);
LLFloaterReg::add("publish_classified_fs", "floater_publish_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSPublishClassifiedFloater>);

View File

@ -55,6 +55,7 @@
#include "m3math.h"
#include "m4math.h"
#include "llmatrix4a.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
#if !LL_DARWIN && !LL_LINUX
extern PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB;
@ -222,6 +223,7 @@ int compare_int(const void *a, const void *b)
//--------------------------------------------------------------------
U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
{
LL_PROFILE_ZONE_SCOPED;
if (!mValid || !mMesh || !mFace || !mVisible ||
!mFace->getVertexBuffer() ||
mMesh->getNumFaces() == 0 ||
@ -230,6 +232,15 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
return 0;
}
// <FS:Beq> render time capture
// TODO(Beq) This path does not appear to have attachments. Prove this then remove.
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{};
auto vobj = mFace->getViewerObject();
if( vobj && vobj->isAttachment() )
{
trackAttachments( vobj, mFace->isState(LLFace::RIGGED), &ratPtr );
}
// </FS:Beq>
U32 triangle_count = 0;
S32 diffuse_channel = LLDrawPoolAvatar::sDiffuseChannel;

View File

@ -3868,6 +3868,9 @@ bool check_avatar_render_mode(U32 mode)
return FSAvatarRenderPersistence::instance().getAvatarRenderSettings(avatar->getID()) == LLVOAvatar::AV_ALWAYS_RENDER;
// [/RLVa:KB]
// return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_ALWAYS_RENDER);
case 4:
return FSAvatarRenderPersistence::instance().getAvatarRenderSettings(avatar->getID()) != LLVOAvatar::AV_RENDER_NORMALLY;
// return FSAvatarRenderPersistence::instance().getAvatarRenderSettings(avatar->getID()) == LLVOAvatar::AV_RENDER_NORMALLY;
default:
return false;
}
@ -3895,6 +3898,8 @@ class LLAvatarCheckImpostorMode : public view_listener_t
// return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_DO_NOT_RENDER);
// case 2:
// return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_ALWAYS_RENDER);
// case 4:
// return (avatar->getVisualMuteSettings() != LLVOAvatar::AV_RENDER_NORMALLY);
// default:
// return false;
//}

View File

@ -1361,6 +1361,7 @@ bool LLViewerOctreeCull::earlyFail(LLViewerOctreeGroup* group)
//virtual
void LLViewerOctreeCull::traverse(const OctreeNode* n)
{
LL_PROFILE_ZONE_SCOPED;
LLViewerOctreeGroup* group = (LLViewerOctreeGroup*) n->getListener(0);
if (earlyFail(group))
@ -1371,14 +1372,17 @@ void LLViewerOctreeCull::traverse(const OctreeNode* n)
if (mRes == 2 ||
(mRes && group->hasState(LLViewerOctreeGroup::SKIP_FRUSTUM_CHECK)))
{ //fully in, just add everything
LL_PROFILE_ZONE_NAMED("AllInside");
OctreeTraveler::traverse(n);
}
else
{
LL_PROFILE_ZONE_NAMED("Check inside?");
mRes = frustumCheck(group);
if (mRes)
{ //at least partially in, run on down
LL_PROFILE_ZONE_NAMED("PartiallyIn");
OctreeTraveler::traverse(n);
}

View File

@ -3810,13 +3810,13 @@ void append_xui_tooltip(LLView* viewp, LLToolTip::Params& params)
}
}
static LLTrace::BlockTimerStatHandle ftm("Update UI");
static LLTrace::BlockTimerStatHandle FTM_UPDATE_UI("Update UI"); // <FS:Beq/> rename to sensible symbol
// Update UI based on stored mouse position from mouse-move
// event processing.
void LLViewerWindow::updateUI()
{
LL_RECORD_BLOCK_TIME(ftm);
LL_RECORD_BLOCK_TIME(FTM_UPDATE_UI); // <FS:Beq/> rename to sensible symbol
static std::string last_handle_msg;

View File

@ -134,6 +134,7 @@
#include "fslslbridge.h" // <FS:PP> Movelock position refresh
#include "fsdiscordconnect.h" // <FS:LO> tapping a place that happens on landing in world to start up discord
#include "fsperfstats.h" // <FS:Beq> performance stats support
extern F32 SPEED_ADJUST_MAX;
extern F32 SPEED_ADJUST_MAX_SEC;
@ -601,7 +602,6 @@ bool LLVOAvatar::sLimitNonImpostors = false; // True unless RenderAvatarMaxNonIm
F32 LLVOAvatar::sRenderDistance = 256.f;
S32 LLVOAvatar::sNumVisibleAvatars = 0;
S32 LLVOAvatar::sNumLODChangesThisFrame = 0;
// const LLUUID LLVOAvatar::sStepSoundOnLand("e8af4a28-aa83-4310-a7c4-c047e15ea0df"); - <FS:PP> Commented out for FIRE-3169: Option to change the default footsteps sound
const LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] =
{
@ -2696,7 +2696,10 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
LL_INFOS() << "Warning! Idle on dead avatar" << LL_ENDL;
return;
}
// <FS:Beq> record time and refresh "tooSlow" status
FSPerfStats::RecordAvatarTime T(getID(), FSPerfStats::StatType_t::RENDER_IDLE); // per avatar "idle" time.
updateTooSlow();
// </FS:Beq>;
// <FS:CR> Use LLCachedControl
static LLCachedControl<bool> disable_all_render_types(gSavedSettings, "DisableAllRenderTypes");
if (!(gPipeline.hasRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR))
@ -2704,7 +2707,11 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
&& !(disable_all_render_types) && !isSelf())
// </FS:CR>
{
return;
if (!mIsControlAvatar)
{
idleUpdateNameTag( mLastRootPos );
}
return;
}
// Update should be happening max once per frame.
@ -2736,7 +2743,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
//</FS:Beq>
}
LLScopedContextString str("avatar_idle_update " + getFullname());
// LLScopedContextString str("avatar_idle_update " + getFullname()); // <FS:Beq> remove unused scoped string
checkTextureLoading() ;
@ -3399,14 +3406,12 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
fRlvShowAvName = (fRlvShowAvTag) && (RlvActions::canShowName(RlvActions::SNC_DEFAULT, getID()));
}
// [/RLVa:KB]
BOOL visible_avatar = isVisible() || mNeedsAnimUpdate;
BOOL visible_chat = useChatBubbles && (mChats.size() || mTyping);
BOOL visible_typing = useTypingBubbles && mTyping;
BOOL render_name = visible_chat ||
visible_typing ||
(visible_avatar &&
// [RLVa:KB] - Checked: RLVa-2.0.1
(fRlvShowAvTag) &&
((fRlvShowAvTag) &&
// [/RLVa:KB]
((sRenderName == RENDER_NAME_ALWAYS) ||
(sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME)));
@ -4209,6 +4214,7 @@ void LLVOAvatar::slamPosition()
bool LLVOAvatar::isVisuallyMuted()
{
LL_PROFILE_ZONE_SCOPED; // <FS:Beq/> Tracy accounting for imposter testing.
bool muted = false;
// <FS:Ansariel> FIRE-11783: Always visually mute avatars that are muted
@ -4261,6 +4267,7 @@ bool LLVOAvatar::isVisuallyMuted()
bool LLVOAvatar::isInMuteList() const
{
LL_PROFILE_ZONE_SCOPED; // <FS:Beq/> Tracy accounting for imposter testing.
bool muted = false;
F64 now = LLFrameTimer::getTotalSeconds();
if (now < mCachedMuteListUpdateTime)
@ -4694,11 +4701,12 @@ void LLVOAvatar::updateFootstepSounds()
void LLVOAvatar::computeUpdatePeriod()
{
bool visually_muted = isVisuallyMuted();
bool slow = isTooSlowWithoutShadows();// <FS:Beq/> the geometry alone is forcing this to be slow so we must imposter
if (mDrawable.notNull()
&& isVisible()
&& (!isSelf() || visually_muted)
&& !isUIAvatar()
&& (sLimitNonImpostors || visually_muted)
&& (sLimitNonImpostors || visually_muted || slow) // <FS:Beq/> imposter slow avatars irrespective of nonimposter setting.
&& !mNeedsAnimUpdate
&& !sFreezeCounter)
{
@ -4710,8 +4718,11 @@ void LLVOAvatar::computeUpdatePeriod()
const S32 UPDATE_RATE_SLOW = 64;
const S32 UPDATE_RATE_MED = 48;
const S32 UPDATE_RATE_FAST = 32;
if (visually_muted)
if(slow)
{
mUpdatePeriod = UPDATE_RATE_FAST;
}
else if (visually_muted)
{ // visually muted avatars update at lowest rate
mUpdatePeriod = UPDATE_RATE_SLOW;
}
@ -5569,6 +5580,7 @@ bool LLVOAvatar::shouldAlphaMask()
//-----------------------------------------------------------------------------
U32 LLVOAvatar::renderSkinned()
{
LL_PROFILE_ZONE_SCOPED; // <FS:Beq/> Tracy accounting for imposter testing.
U32 num_indices = 0;
if (!mIsBuilt)
@ -5805,6 +5817,7 @@ U32 LLVOAvatar::renderSkinned()
U32 LLVOAvatar::renderTransparent(BOOL first_pass)
{
LL_PROFILE_ZONE_SCOPED; // <FS:Beq/> Tracy accounting for render tracking
U32 num_indices = 0;
if( isWearingWearableType( LLWearableType::WT_SKIRT ) && (isUIAvatar() || isTextureVisible(TEX_SKIRT_BAKED)) )
{
@ -5857,6 +5870,7 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass)
//-----------------------------------------------------------------------------
U32 LLVOAvatar::renderRigid()
{
LL_PROFILE_ZONE_SCOPED; // <FS:Beq/> Tracy accounting for render tracking
U32 num_indices = 0;
if (!mIsBuilt)
@ -5906,6 +5920,7 @@ U32 LLVOAvatar::renderRigid()
U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel)
{
LL_PROFILE_ZONE_SCOPED; // <FS:Beq/> Tracy accounting for render tracking
if (!mImpostor.isComplete())
{
return 0;
@ -6921,6 +6936,7 @@ const LLUUID& LLVOAvatar::getID() const
LLJoint *LLVOAvatar::getJoint( const JointKey &name )
// </FS:ND>
{
LL_PROFILE_ZONE_SCOPED;
//<FS:ND> Query by JointKey rather than just a string, the key can be a U32 index for faster lookup
//joint_map_t::iterator iter = mJointMap.find( name );
@ -9116,6 +9132,95 @@ BOOL LLVOAvatar::isFullyLoaded() const
// return (mRenderUnloadedAvatar || mFullyLoaded);
}
// <FS:Beq> use Avatar Render Time as complexity metric
// markARTStale - Mark stale and set the frameupdate to now so that we can wait at least one frame to get a revised number.
void LLVOAvatar::markARTStale()
{
mARTStale=true;
mLastARTUpdateFrame = LLFrameTimer::getFrameCount();
}
// Udpate Avatar state based on render time
void LLVOAvatar::updateTooSlow()
{
LL_PROFILE_ZONE_SCOPED;
static LLCachedControl<bool> alwaysRenderFriends(gSavedSettings, "AlwaysRenderFriends");
static LLCachedControl<bool> allowSelfImpostor(gSavedSettings, "FSAllowSelfImpostor");
const auto id = getID();
// mTooSlow - Is the avatar flagged as being slow (includes shadow time)
// mTooSlowWithoutShadows - Is the avatar flagged as being slow even with shadows removed.
// mARTStale - the rendertime we have is stale because of an update. We need to force a re-render to re-assess slowness
if( mARTStale )
{
if ( LLFrameTimer::getFrameCount() - mLastARTUpdateFrame < 5 )
{
// LL_INFOS() << this->getFullname() << " marked stale " << LL_ENDL;
// we've not had a chance to update yet (allow a few to be certain a full frame has passed)
return;
}
mARTStale = false;
mTooSlow = false;
mTooSlowWithoutShadows = false;
// LL_INFOS() << this->getFullname() << " refreshed ART combined = " << mRenderTime << " @ " << mLastARTUpdateFrame << LL_ENDL;
}
// Either we're not stale or we've updated.
U64 render_time_raw;
U64 render_geom_time_raw;
if( !mTooSlow )
{
// we are fully rendered, so we use the live values
std::lock_guard<std::mutex> lock{FSPerfStats::bufferToggleLock};
render_time_raw = FSPerfStats::StatsRecorder::get(FSPerfStats::ObjType_t::OT_AVATAR, id, FSPerfStats::StatType_t::RENDER_COMBINED);
render_geom_time_raw = FSPerfStats::StatsRecorder::get(FSPerfStats::ObjType_t::OT_AVATAR, id, FSPerfStats::StatType_t::RENDER_GEOMETRY);
}
else
{
// use the cached values.
render_time_raw = mRenderTime;
render_geom_time_raw = mGeomTime;
}
if( (FSPerfStats::renderAvatarMaxART_ns > 0) &&
(FSPerfStats::raw_to_ns(render_time_raw) >= FSPerfStats::renderAvatarMaxART_ns) )
{
if( !mTooSlow ) // if we were previously not slow (with or without shadows.)
{
// if we weren't capped, we are now
mLastARTUpdateFrame = LLFrameTimer::getFrameCount();
mRenderTime = render_time_raw;
mGeomTime = render_geom_time_raw;
mARTStale = false;
mTooSlow = true;
}
if(!mTooSlowWithoutShadows) // if we were not previously above the full impostor cap
{
bool render_friend_or_exception = ( alwaysRenderFriends && LLAvatarTracker::instance().isBuddy( id ) ) ||
( getVisualMuteSettings() == LLVOAvatar::AV_ALWAYS_RENDER );
if( (!isSelf() || allowSelfImpostor) && !render_friend_or_exception )
{
// Note: slow rendering Friends still get their shadows zapped.
mTooSlowWithoutShadows = (FSPerfStats::raw_to_ns(render_geom_time_raw) >= FSPerfStats::renderAvatarMaxART_ns);
}
}
}
else
{
// LL_INFOS() << this->getFullname() << " ("<< (combined?"combined":"geometry") << ") good render time = " << FSPerfStats::raw_to_ns(render_time_raw) << " vs ("<< LLVOAvatar::sRenderTimeCap_ns << " set @ " << mLastARTUpdateFrame << LL_ENDL;
mTooSlow = false;
mTooSlowWithoutShadows = false;
}
if(mTooSlow)
{
FSPerfStats::tunedAvatars++; // <FS:Beq> increment the number of avatars that have been tweaked.
}
}
// </FS:Beq>
bool LLVOAvatar::isTooComplex() const
{
bool too_complex;
@ -10130,7 +10235,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
//bool enable_verbose_dumps = gSavedSettings.getBOOL("DebugAvatarAppearanceMessage");
static LLCachedControl<bool> enable_verbose_dumps(gSavedSettings, "DebugAvatarAppearanceMessage");
// </FS:CR>
std::string dump_prefix = getFullname() + "_" + (isSelf()?"s":"o") + "_";
if (gSavedSettings.getBOOL("BlockAvatarAppearanceMessages"))
{
LL_WARNS() << "Blocking AvatarAppearance message" << LL_ENDL;
@ -10143,6 +10247,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
parseAppearanceMessage(mesgsys, *contents);
if (enable_verbose_dumps)
{
std::string dump_prefix = getFullname() + "_" + (isSelf()?"s":"o") + "_";
dumpAppearanceMsgParams(dump_prefix + "appearance_msg", *contents);
}
@ -10424,7 +10529,6 @@ void LLVOAvatar::applyParsedAppearanceMessage(LLAppearanceMessageContents& conte
updateMeshTextures();
updateMeshVisibility();
}
LLViewerTexture* LLVOAvatar::getBakedTexture(const U8 te)
@ -11407,7 +11511,14 @@ void LLVOAvatar::updateImpostors()
// virtual
BOOL LLVOAvatar::isImpostor()
{
return isVisuallyMuted() || (sLimitNonImpostors && (mUpdatePeriod > 1));
// <FS:Beq> render time handling using tooSlow()
// return isVisuallyMuted() || (sLimitNonImpostors && (mUpdatePeriod > 1));
return (
isVisuallyMuted() ||
isTooSlowWithoutShadows() ||
(sLimitNonImpostors && (mUpdatePeriod > 1) )
);
// </FS:Beq>
}
BOOL LLVOAvatar::shouldImpostor(const F32 rank_factor)
@ -11420,6 +11531,15 @@ BOOL LLVOAvatar::shouldImpostor(const F32 rank_factor)
{
return true;
}
// <FS:Beq> render time handling using tooSlow()
// return sLimitNonImpostors && (mVisibilityRank > sMaxNonImpostors * rank_factor);
// static LLCachedControl<bool> render_jellys_As_imposters(gSavedSettings, "RenderJellyDollsAsImpostors");
if (isTooSlowWithoutShadows())
{
return true;
}
// </FS:Beq>
return sLimitNonImpostors && (mVisibilityRank > sMaxNonImpostors * rank_factor);
}
@ -11595,6 +11715,7 @@ void LLVOAvatar::updateVisualComplexity()
LL_DEBUGS("AvatarRender") << "avatar " << getID() << " appearance changed" << LL_ENDL;
// Set the cache time to in the past so it's updated ASAP
mVisualComplexityStale = true;
markARTStale();
}
// Account for the complexity of a single top-level object associated
@ -11606,6 +11727,7 @@ void LLVOAvatar::accountRenderComplexityForObject(
LLVOVolume::texture_cost_t& textures,
U32& cost,
hud_complexity_list_t& hud_complexity_list,
object_complexity_list_t& object_complexity_list,
// <FS:Ansariel> Show per-item complexity in COF
std::map<LLUUID, U32>& item_complexity,
std::map<LLUUID, U32>& temp_item_complexity)
@ -11628,12 +11750,12 @@ void LLVOAvatar::accountRenderComplexityForObject(
F32 attachment_volume_cost = 0;
F32 attachment_texture_cost = 0;
F32 attachment_children_cost = 0;
const F32 animated_object_attachment_surcharge = 1000;
const F32 animated_object_attachment_surcharge = 1000;
if (attached_object->isAnimatedObject())
{
attachment_volume_cost += animated_object_attachment_surcharge;
}
if (attached_object->isAnimatedObject())
{
attachment_volume_cost += animated_object_attachment_surcharge;
}
attachment_volume_cost += volume->getRenderCost(textures);
const_child_list_t children = volume->getChildren();
@ -11668,6 +11790,15 @@ void LLVOAvatar::accountRenderComplexityForObject(
// Limit attachment complexity to avoid signed integer flipping of the wearer's ACI
cost += (U32)llclamp(attachment_total_cost, MIN_ATTACHMENT_COMPLEXITY, max_attachment_complexity);
if (isSelf())
{
LLObjectComplexity object_complexity;
object_complexity.objectName = attached_object->getAttachmentItemName();
object_complexity.objectId = attached_object->getAttachmentItemID();
object_complexity.objectCost = attachment_total_cost;
object_complexity_list.push_back(object_complexity);
}
// <FS:Ansariel> Show per-item complexity in COF
if (isSelf())
{
@ -11679,8 +11810,8 @@ void LLVOAvatar::accountRenderComplexityForObject(
{
temp_item_complexity.insert(std::make_pair(attached_object->getID(), (U32)attachment_total_cost));
}
}
// </FS:Ansariel>
}
}
}
}
@ -11775,6 +11906,8 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
U32 cost = VISUAL_COMPLEXITY_UNKNOWN;
LLVOVolume::texture_cost_t textures;
hud_complexity_list_t hud_complexity_list;
object_complexity_list_t object_complexity_list;
//<FS:Beq> BOM constrain number of bake requests when BOM not supported
// for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
for (U8 baked_index = 0; baked_index < getNumBakes(); baked_index++)
@ -11822,8 +11955,8 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
{
accountRenderComplexityForObject(volp, max_attachment_complexity,
// <FS:Ansariel> Show per-item complexity in COF
//textures, cost, hud_complexity_list);
textures, cost, hud_complexity_list, item_complexity, temp_item_complexity);
//textures, cost, hud_complexity_list, object_complexity_list);
textures, cost, hud_complexity_list, object_complexity_list, item_complexity, temp_item_complexity);
// </FS:Ansariel>
}
}
@ -11849,8 +11982,8 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
const LLViewerObject* attached_object = attachment_iter->get();
accountRenderComplexityForObject(attached_object, max_attachment_complexity,
// <FS:Ansariel> Show per-item complexity in COF
//textures, cost, hud_complexity_list);
textures, cost, hud_complexity_list, item_complexity, temp_item_complexity);
//textures, cost, hud_complexity_list, object_complexity_list);
textures, cost, hud_complexity_list, object_complexity_list, item_complexity, temp_item_complexity);
// </FS:Ansariel>
}
}
@ -11912,13 +12045,13 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
mVisualComplexity = cost;
mVisualComplexityStale = false;
static LLCachedControl<U32> show_my_complexity_changes(gSavedSettings, "ShowMyComplexityChanges", 20);
if (isSelf() && show_my_complexity_changes)
if (isSelf())
{
// Avatar complexity
LLAvatarRenderNotifier::getInstance()->updateNotificationAgent(mVisualComplexity);
LLAvatarRenderNotifier::getInstance()->setObjectComplexityList(object_complexity_list);
// HUD complexity
LLHUDRenderNotifier::getInstance()->updateNotificationHUD(hud_complexity_list);
}
@ -11937,6 +12070,7 @@ void LLVOAvatar::setVisualMuteSettings(VisualMuteSettings set)
mVisuallyMuteSetting = set;
mNeedsImpostorUpdate = TRUE;
mLastImpostorUpdateReason = 7;
markARTStale();// <FS:Beq> Force a refresh of the ART to take into account new setting.
// <FS:Ansariel> [FS Persisted Avatar Render Settings]
//LLRenderMuteList::getInstance()->saveVisualMuteSetting(getID(), S32(set));
@ -12089,7 +12223,7 @@ LLVOAvatar::AvatarOverallAppearance LLVOAvatar::getOverallAppearance() const
}
else // !isSelf()
{
if (isInMuteList())
if (isInMuteList())
{
result = AOA_INVISIBLE;
}

View File

@ -311,6 +311,7 @@ public:
LLVOVolume::texture_cost_t& textures,
U32& cost,
hud_complexity_list_t& hud_complexity_list,
object_complexity_list_t& object_complexity_list,
// <FS:Ansariel> Show per-item complexity in COF
std::map<LLUUID, U32>& item_complexity,
std::map<LLUUID, U32>& temp_item_complexity);
@ -354,6 +355,7 @@ public:
static F32 sPhysicsLODFactor; // user-settable physics LOD factor
static BOOL sJointDebug; // output total number of joints being touched for each avatar
static BOOL sDebugAvatarRotation;
static U64 sRenderTimeLimit_ns; // <FS:Beq/> nanosecond time limit for avatar rendering 0 is unlimited.
static LLPartSysData sCloud;
//--------------------------------------------------------------------
@ -367,6 +369,17 @@ public:
//--------------------------------------------------------------------
public:
BOOL isFullyLoaded() const;
// <FS:Beq> check and return current state relative to limits
// default will test only the geometry (combined=false).
// this allows us to disable shadows separately on complex avatars.
inline bool isTooSlowWithShadows() const {return mTooSlow;};
inline bool isTooSlowWithoutShadows() const {return mTooSlowWithoutShadows;};
inline bool isTooSlow(bool combined = false) const
{
return(combined?mTooSlow:mTooSlowWithoutShadows);
}
void updateTooSlow();
// </FS:Beq>
virtual bool isTooComplex() const; // <FS:Ansariel> FIRE-29012: Standalone animesh avatars get affected by complexity limit; changed to virtual
bool visualParamWeightsAreDefault();
virtual bool getIsCloud() const;
@ -388,6 +401,7 @@ public:
void logMetricsTimerRecord(const std::string& phase_name, F32 elapsed, bool completed);
void calcMutedAVColor();
void markARTStale();
protected:
LLViewerStats::PhaseMap& getPhases() { return mPhases; }
@ -405,6 +419,15 @@ private:
LLColor4 mMutedAVColor;
LLFrameTimer mFullyLoadedTimer;
LLFrameTimer mRuthTimer;
U32 mLastARTUpdateFrame{0};
U64 mRenderTime{0};
U64 mGeomTime{0};
bool mARTStale{true};
bool mARTCapped{false};
// <FS:Beq> variables to hold "slowness" status
bool mTooSlow{false};
bool mTooSlowWithoutShadows{false};
// </FS:Beq>
private:
LLViewerStats::PhaseMap mPhases;
@ -1188,6 +1211,8 @@ public:
// COF version of last appearance message received for this av.
S32 mLastUpdateReceivedCOFVersion;
U64 getLastART() const { return mRenderTime; }
/** Diagnostics
** **
*******************************************************************************/

View File

@ -91,6 +91,7 @@
#include "rlvlocks.h"
// [/RLVa:KB]
#include "llviewernetwork.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
const F32 FORCE_CULL_AREA = 8.f;
@ -5545,7 +5546,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
}
}
if (type == LLRenderPass::PASS_ALPHA)
// if (type == LLRenderPass::PASS_ALPHA) // <FS:Beq> allow tracking through pipeline
{ //for alpha sorting
facep->setDrawInfo(draw_info);
}
@ -5761,6 +5762,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_FACE_LIST);
//get all the faces into a list
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{}; // <FS:Beq/> render time capture
for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin();
drawable_iter != group->getDataEnd(); ++drawable_iter)
{
@ -5783,6 +5785,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
continue;
}
//<FS:Beq> Stop doing stupid stuff we don;t need to.
// Moving this inside a debug enabled check
// std::string vobj_name = llformat("Vol%p", vobj);
@ -5793,6 +5796,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
{
continue;
}
// <FS:Beq> Capture render times
if(vobj->isAttachment())
{
trackAttachments( vobj, drawablep->isState(LLDrawable::RIGGED),&ratPtr);
}
// </FS:Beq>
LLVolume* volume = vobj->getVolume();
if (volume)
@ -6360,7 +6369,7 @@ static LLTrace::BlockTimerStatHandle FTM_REBUILD_MESH_FLUSH("Flush Mesh");
void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
{
llassert(group);
LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB);// <FS:Beq> move out one scope (but are these even useful as dupes?)
// LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB);// <FS:Beq> High volume remove (roughly 1000:1 ratio to inside the if statement)
if (group && group->hasState(LLSpatialGroup::MESH_DIRTY) && !group->hasState(LLSpatialGroup::GEOM_DIRTY))
{
LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB);
@ -6381,13 +6390,21 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
U32 buffer_count = 0;
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{}; // <FS:Beq/> capture render times
for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
{
LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable();
if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) )
{
LL_PROFILE_ZONE_NAMED("Rebuild all non-Rigged");
LLVOVolume* vobj = drawablep->getVOVolume();
// <FS:Beq> capture render times
if( vobj && vobj->isAttachment() )
{
trackAttachments( vobj, drawablep->isState(LLDrawable::RIGGED), &ratPtr );
}
// </FS:Beq>
//<FS:Beq> avoid unfortunate sleep during trylock by static check
//if(debugLoggingEnabled("AnimatedObjectsLinkset"))
static auto debug_logging_on = debugLoggingEnabled("AnimatedObjectsLinkset");
@ -6801,10 +6818,18 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
U32 indices_index = 0;
U16 index_offset = 0;
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr; // <FS:Beq/> capture render times
while (face_iter < i)
{
//update face indices for new buffer
facep = *face_iter;
LLViewerObject* vobj = facep->getViewerObject();
// <FS:Beq> capture render times
if(vobj && vobj->isAttachment())
{
trackAttachments(vobj, LLPipeline::sShadowRender, &ratPtr);
}
// </FS:Beq>
if (buffer.isNull())
{
// Bulk allocation failed
@ -7020,8 +7045,12 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
else if (is_alpha)
{
// can we safely treat this as an alpha mask?
if (facep->getFaceColor().mV[3] <= 0.f)
// <FS:Beq> Nothing actually sets facecolor use the TE alpha instead.
// if (facep->getFaceColor().mV[3] <= 0.f)
if (te->getAlpha() <=0.f || facep->getFaceColor().mV[3] <= 0.f)
// </FS:Beq>
{ //100% transparent, don't render unless we're highlighting transparent
LL_PROFILE_ZONE_NAMED("facep->alpha -> invisible");
registerFace(group, facep, LLRenderPass::PASS_ALPHA_INVISIBLE);
}
else if (facep->canRenderAsMask())

View File

@ -370,6 +370,7 @@ bool LLPipeline::sReflectionRender = false;
bool LLPipeline::sDistortionRender = false;
bool LLPipeline::sImpostorRender = false;
bool LLPipeline::sImpostorRenderAlphaDepthPass = false;
bool LLPipeline::sShowJellyDollAsImpostor = true;
bool LLPipeline::sUnderWaterRender = false;
bool LLPipeline::sTextureBindTest = false;
bool LLPipeline::sRenderFrameTest = false;
@ -1195,6 +1196,7 @@ void LLPipeline::refreshCachedSettings()
LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred");
LLPipeline::sAutoMaskAlphaNonDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaNonDeferred");
LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip");
LLPipeline::sShowJellyDollAsImpostor = gSavedSettings.getBOOL("RenderJellyDollsAsImpostors");
LLVOAvatar::sMaxNonImpostors = gSavedSettings.getU32("RenderAvatarMaxNonImpostors");
LLVOAvatar::updateImpostorRendering(LLVOAvatar::sMaxNonImpostors);
LLPipeline::sDelayVBUpdate = gSavedSettings.getBOOL("RenderDelayVBUpdate");
@ -2829,6 +2831,7 @@ void LLPipeline::doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderT
void LLPipeline::doOcclusion(LLCamera& camera)
{
LL_PROFILE_ZONE_NAMED("doOcclusion");
if (LLPipeline::sUseOcclusion > 1 && !LLSpatialPartition::sTeleportRequested &&
(sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck))
{
@ -3544,6 +3547,8 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
//LLVertexBuffer::unbind();
grabReferences(result);
{
LL_PROFILE_ZONE_NAMED("checkOcclusionAndRebuildMesh");
for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
{
LLSpatialGroup* group = *iter;
@ -3567,9 +3572,11 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
}
}
}
}
if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
{
LL_PROFILE_ZONE_NAMED("WorldCamera");
LLSpatialGroup* last_group = NULL;
BOOL fov_changed = LLViewerCamera::getInstance()->isDefaultFOVChanged();
for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
@ -3603,7 +3610,8 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
last_group->mLastUpdateDistance = last_group->mDistance;
}
}
{
LL_PROFILE_ZONE_NAMED("StateSort: visible groups");
for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
{
LLSpatialGroup* group = *iter;
@ -3622,7 +3630,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
group->rebuildMesh();
}
}
}
}}
{
LL_RECORD_BLOCK_TIME(FTM_STATESORT_DRAWABLE);
@ -3978,6 +3986,8 @@ void LLPipeline::postSort(LLCamera& camera)
LL_PUSH_CALLSTACKS();
//rebuild drawable geometry
{
LL_PROFILE_ZONE_NAMED("PostSort: rebuildGeom");
for (LLCullResult::sg_iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i)
{
LLSpatialGroup* group = *i;
@ -3996,6 +4006,8 @@ void LLPipeline::postSort(LLCamera& camera)
//build render map
{
LL_PROFILE_ZONE_NAMED("build render map");
for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
{
LLSpatialGroup* group = *i;
@ -4041,6 +4053,7 @@ void LLPipeline::postSort(LLCamera& camera)
if (hasRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA))
{
LL_PROFILE_ZONE_NAMED("Collect Alpha groups");
LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
if (alpha != group->mDrawMap.end())
@ -4066,6 +4079,7 @@ void LLPipeline::postSort(LLCamera& camera)
}
}
}
}
//flush particle VB
if (LLVOPartGroup::sVB)
@ -4091,12 +4105,15 @@ void LLPipeline::postSort(LLCamera& camera)
glBeginQueryARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, mMeshDirtyQueryObject);
}*/
{
LL_PROFILE_ZONE_NAMED("rebuild delayed upd groups");
//pack vertex buffers for groups that chose to delay their updates
for (LLSpatialGroup::sg_vector_t::iterator iter = mMeshDirtyGroup.begin(); iter != mMeshDirtyGroup.end(); ++iter)
{
(*iter)->rebuildMesh();
}
}
}
/*if (use_transform_feedback)
{
@ -4105,12 +4122,17 @@ void LLPipeline::postSort(LLCamera& camera)
mMeshDirtyGroup.clear();
{
LL_PROFILE_ZONE_NAMED("sort alpha groups");
if (!sShadowRender)
{
std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater());
}
}
LL_PUSH_CALLSTACKS();
{
LL_PROFILE_ZONE_NAMED("beacon rendering flags");
// only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus
// Ansariel: Make beacons also show when beacons floater is closed.
if (/*LLFloaterReg::instanceVisible("beacons") &&*/ !sShadowRender)
@ -4164,6 +4186,7 @@ void LLPipeline::postSort(LLCamera& camera)
forAllVisibleDrawables(renderSoundHighlights);
}
}
}
LL_PUSH_CALLSTACKS();
// If managing your telehub, draw beacons at telehub and currently selected spawnpoint.
if (LLFloaterTelehub::renderBeacons())
@ -4173,6 +4196,7 @@ void LLPipeline::postSort(LLCamera& camera)
if (!sShadowRender)
{
LL_PROFILE_ZONE_NAMED("Render face highlights");
mSelectedFaces.clear();
LLPipeline::setRenderHighlightTextureChannel(gFloaterTools->getPanelFace()->getTextureChannelToEdit());
@ -11248,9 +11272,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
<< " is " << ( too_complex ? "" : "not ") << "too complex"
<< LL_ENDL;
bool too_slow = avatar->isTooSlowWithoutShadows(); // <FS:Beq/> only if we really have to do we imposter.
pushRenderTypeMask();
if (visually_muted || too_complex)
if ( !too_slow && ( visually_muted || too_complex ) )
{
andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR,
LLPipeline::RENDER_TYPE_CONTROL_AV,

View File

@ -600,6 +600,7 @@ public:
static bool sDistortionRender;
static bool sImpostorRender;
static bool sImpostorRenderAlphaDepthPass;
static bool sShowJellyDollAsImpostor;
static bool sUnderWaterRender;
static bool sRenderGlow;
static bool sTextureBindTest;

View File

@ -1318,6 +1318,12 @@
<color
name="OutfitGalleryItemUnselected"
value="0.4 0.4 0.4 1" />
<color
name="PanelGray"
value="0.27 0.27 0.27 1" />
<color
name="PerformanceMid"
value="1 0.8 0 1" />
<!-- <FS:CR> Script Editor Colors -->
<color

View File

@ -1315,6 +1315,12 @@
<color
name="OutfitGalleryItemUnselected"
value="0.4 0.4 0.4 1" />
<color
name="PanelGray"
value="0.27 0.27 0.27 1" />
<color
name="PerformanceMid"
value="1 0.8 0 1" />
<!-- <FS:CR> Script Editor Colors -->
<color

View File

@ -1270,8 +1270,11 @@
name="OutfitGalleryItemUnselected"
value="0.4 0.4 0.4 1" />
<color
name="AddPaymentPanel"
name="PanelGray"
value="0.27 0.27 0.27 1" />
<color
name="PerformanceMid"
value="1 0.8 0 1" />
<!-- <FS:CR> Script Editor Colors -->
<color

View File

@ -158,6 +158,7 @@ with the same filename but different name
<texture name="Command_Move_Icon" file_name="toolbar_icons/move.png" preload="true" />
<texture name="Command_Environments_Icon" file_name="toolbar_icons/environments.png" preload="true" />
<texture name="Command_People_Icon" file_name="toolbar_icons/people.png" preload="true" />
<texture name="Command_Performance_Icon" file_name="toolbar_icons/performance.png" preload="true" />
<texture name="Command_Picks_Icon" file_name="toolbar_icons/picks.png" preload="true" />
<texture name="Command_Places_Icon" file_name="toolbar_icons/places.png" preload="true" />
<texture name="Command_Preferences_Icon" file_name="toolbar_icons/preferences.png" preload="true" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="floater_avatar_render_settings" title="EINSTELLUNGEN ZUR DARSTELLUNG VON AVATAREN">
<floater name="floater_avatar_render_settings" title="Ausnahmen Avatardarstellung">
<string name="av_never_render" value="Nie"/>
<string name="av_always_render" value="Immer"/>
<filter_editor label="Nach Personen filtern" name="people_filter_input"/>
<menu_button name="plus_btn" tool_tip="Aktionen für ausgewählte Person"/>
<name_list name="render_settings_list">
<name_list.columns label="Name" name="name"/>
<name_list.columns label="Darstellungseinstellung" name="setting"/>
<name_list.columns label="Hinzugefügt am" name="timestamp"/>
<name_list.columns label="Komplette Details" name="setting"/>
</name_list>
<panel name="add_subpanel">
<menu_button name="plus_btn" label="Hinzufügen..." tool_tip="Aktionen für ausgewählte Person"/>
</panel>
</floater>

View File

@ -1,16 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="avatarrendersettings" title="Avatar-Anzeigeeinstellungen">
<floater name="avatarrendersettings" title="Avatar-Anzeigeausnahmen">
<floater.string name="av_render_never">
Niemals
</floater.string>
<floater.string name="av_render_always">
Komplett
Immer
</floater.string>
<filter_editor label="Avatare filtern" name="filter_input"/>
<menu_button name="plus_btn" tool_tip="Person zur Liste hinzufügen"/>
<name_list name="avatar_list">
<name_list.columns label="Name" name="name"/>
<name_list.columns label="Anzeigeeinstellung" name="render_setting" width="125"/>
<name_list.columns label="Komplette Details" name="render_setting" width="125"/>
</name_list>
<button name="close_btn" label="Schließen"/>
</floater>

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="performance" title="Grafik-Performance-Verbesserung (experimentell)">
<floater.string name="frame_stats">
Frame: [TOT_FRAME_TIME]ms - Szenerie:[SCENERY_FRAME_PCT]% Avatare:[AV_FRAME_PCT]% UI:[UI_FRAME_PCT]% HUDs:[HUDS_FRAME_PCT]% Swap:[SWAP_FRAME_PCT]% Tasks:[IDLE_FRAME_PCT]%
</floater.string>
<floater.string name="limit_fps">
FPS limitiert auf [FPSCAP] FPS
</floater.string>
<floater.string name="tuning_fps">
Auto-Anpassung-Ziel [FPSTARGET] FPS
</floater.string>
<floater.string name="av_frame_pct">
[AV_FRAME_PCT]%
</floater.string>
<floater.string name="huds_frame_pct">
[HUDS_FRAME_PCT]%
</floater.string>
<floater.string name="focus_fps">
Im Hintergrund
</floater.string>
<floater.string name="tot_av_template">
Gesamt: [TOT_AV] ([TOT_AV_TIME]μs)
</floater.string>
<floater.string name="tot_att_template">
Gesamt: [TOT_ATT] ([TOT_ATT_TIME]μs)
</floater.string>
<panel name="panel_top">
<panel name="fps_subpanel">
<text name="fps_lbl">
Bilder pro Sekunde
</text>
<text name="fps_desc1_lbl">
5-10 Sekunden warten auf Effekt der Anpassungen.
</text>
<text name="frame_breakdown">
Frame-Aufschlüsselung erfolgt hier.
</text>
</panel>
<panel name="target_subpanel">
<text name="settings_lbl">
Auto-Anpassung Ziel-FPS
</text>
<check_box label="Auto-Anpassung" name="AutoTuneFPS" tool_tip="Der Viewer wird automatisch versuchen, die Ziel-FPS zu erreichen." />
<text name="settings_desc">
Einstellungen automatisch für FPS anpassen.
</text>
<combo_box name="FSTuningFPSStrategy">
<combo_box.item label="Nur Avatar-Einstellungen" name="av_only" />
<combo_box.item label="Avatar und Szenerie" name="av_and_scene" />
</combo_box>
<spinner name="target_fps" tooltip="Ziel-FPS - Der Viewer wird automatisch versuchen, die gewünschte FPS durch Anpassung der Einstellungen zu erreichen." />
</panel>
</panel>
<panel name="panel_performance_main">
<panel name="settings_subpanel">
<text name="settings_lbl">
Grafik-Einstellungen
</text>
<text name="settings_desc">
Einstellungen für Distanz, Wasser, Beleuchtung uvm.
</text>
</panel>
<panel name="nearby_subpanel">
<text name="avatars_nearby_lbl">
Avatar in der Nähe
</text>
<text name="avatars_nearby_desc">
Einstellen, welche Avatare vollständig dargestellt werden.
</text>
<text name="avatars_frme_pct_lbl">
Benötigte
Renderzeit
für Avatare
</text>
</panel>
<panel name="complexity_subpanel">
<text name="complexity_lbl">
Eigene Avatar-Komplexität
</text>
<text name="complexity_info">
Sei ein guter Einwohner - verwalte den Einfluss des eigenen Avatars.
</text>
</panel>
<panel name="huds_subpanel">
<text name="huds_lbl">
Aktive HUDs
</text>
<text name="huds_desc">
Entfernen von HUDs kann Geschwindigkeit verbessern.
</text>
<text name="huds_frme_pct_lbl">
Benötigte
Renderzeit
für HUDs
</text>
</panel>
</panel>
</floater>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="prefs_graphics_advanced" title="ERWEITERTE GRAFIKEINSTELLUNGEN">
<floater name="prefs_graphics_advanced" title="Erweiterte Grafikeinstellungen">
<text name="GeneralText">
Allgemein
</text>

View File

@ -22,9 +22,9 @@
<menu_item_call label="Hineinzoomen" name="Zoom In"/>
<menu_item_call label="Bezahlen" name="Pay..."/>
<menu_item_call label="Objektprofil" name="Object Inspect"/>
<menu_item_check label="Normal darstellen" name="RenderNormally"/>
<menu_item_check label="Nicht darstellen" name="DoNotRender"/>
<menu_item_check label="Komplett darstellen" name="AlwaysRenderFully"/>
<menu_item_check label="Immer komplett darstellen" name="AlwaysRenderFully"/>
<menu_item_check label="Nie komplett darstellen" name="DoNotRender"/>
<menu_item_check label="Darstellungsausnahme entfernen" name="RenderNormally"/>
<menu_item_call label="Partikeleigentümer blockieren" name="Mute Particle"/>
<menu_item_call label="Untersuchen" name="Object_Inspect_Floater"/>
<menu_item_call label="Skript-Info" name="ScriptInfo"/>

View File

@ -21,9 +21,9 @@
<menu_item_call label="XML ausgeben" name="Dump XML"/>
<menu_item_call label="Hineinzoomen" name="Zoom In"/>
<menu_item_call label="Bezahlen" name="Pay..."/>
<menu_item_check label="Normal darstellen" name="RenderNormally"/>
<menu_item_check label="Nicht darstellen" name="DoNotRender"/>
<menu_item_check label="Komplett darstellen" name="AlwaysRenderFully"/>
<menu_item_check label="Immer komplett darstellen" name="AlwaysRenderFully"/>
<menu_item_check label="Nie komplett darstellen" name="DoNotRender"/>
<menu_item_check label="Darstellungsausnahme entfernen" name="RenderNormally"/>
<menu_item_call label="Nicht anzeigen" name="Derender"/>
<menu_item_call label="Nicht anzeigen &amp; Blacklist" name="DerenderPermanent"/>
<menu_item_call label="Skript-Info" name="ScriptInfo"/>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="Settings">
<menu_item_check label="Standard" name="default"/>
<menu_item_check label="Immer darstellen" name="always_render"/>
<menu_item_check label="Nie darstellen" name="never_render"/>
<menu_item_check label="Immer komplett darstellen" name="always_render"/>
<menu_item_check label="Nie komplett darstellen" name="never_render"/>
<menu_item_check label="Von Ausnahmen entfernen" name="default"/>
</context_menu>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<toggleable_menu name="menu_settings_add.xml">
<menu_item_call label="Einwohner immer darstellen..." name="add_avatar_always_render"/>
<menu_item_call label="Einwohner nie darstellen..." name="add_avatar_never_render"/>
<menu_item_call label="Einwohner immer komplett darstellen..." name="add_avatar_always_render"/>
<menu_item_call label="Einwohner nie komplett darstellen..." name="add_avatar_never_render"/>
</toggleable_menu>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<context_menu name="Avatar Render Settings Menu">
<menu_item_call label="Normal darstellen (entfernt von Liste)" name="av_render_normal"/>
<menu_item_call label="Nicht darstellen" name="av_render_never"/>
<menu_item_call label="Komplett darstellen" name="av_render_always"/>
<menu_item_call label="Immer komplett darstellen" name="av_render_always"/>
<menu_item_call label="Nie komplett darstellen" name="av_render_never"/>
<menu_item_call label="Ausnahme entfernen" name="av_render_normal"/>
</context_menu>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<context_menu name="Settings">
<menu_item_check label="Immer komplett darstellen" name="always_render" />
<menu_item_check label="Nie komplett darstellen" name="never_render" />
<menu_item_check label="Darstellungsausnahme entfernen" name="default" />
<menu_item_call label="Avatar untersuchen" name="inspect" />
<menu_item_call label="Avatar heranzoomen" name="zoom" />
</context_menu>

View File

@ -136,6 +136,7 @@
<menu_item_check label="Koordinaten" name="Coordinates"/>
<menu_item_check label="Parzelleneigenschaften" name="Parcel Properties"/>
<menu_item_check label="Menü „Erweitert“" name="Show Advanced Menu"/>
<menu_item_check label="Grafikgeschwindigkeit verbessern..." name="Performance"/>
</menu>
<menu_item_call label="Nach Hause teleportieren" name="Teleport Home"/>
<menu_item_call label="Diesen Ort als Zuhause festlegen" name="Set Home to Here"/>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_performance_autotune">
<text name="back_lbl">
Zurück
</text>
<text name="settings_title">
Auto-Anpassung-Einstellungen
</text>
<text name="quality_lbl">
Entfernteste Avatare
</text>
<check_box label="Distanz-basierte Optimierung" name="FSAutoTuneImpostorByDistEnabled" tool_tip="Falls aktiviert wird die Einstellung MaxNonImpostors angepasst, um komplett dargestellte Avatare auf den angegebenen Radius zu beschränken." />
<spinner label="Entferntester kompl. Avatar" name="ffa_autotune" />
<text name="distant_av_advice">
Avatare in größerer Entfernung haben weiterhin einen hohen Einfluss.
Entfernung von der Kamera setzen, ab dem ein Avatar optimiert wird.
</text>
<text name="distance_lbl">
Sichtweiten-
Tuning-Limit
</text>
<spinner label="Minimale Distanz" name="min_dd_autotune" />
<spinner label="Präferierte Distanz" name="pref_dd_autotune" />
<text name="distance_desc1">
Beim Anpassen der Szenerie-Parameter wird Auto-Anpassung die Sichtweite zwischen dem Minimum und der Präferenz optimieren.
</text>
<text name="sundry_lbl">
Verschiedene Einstellungen
</text>
<check_box label="Optimierung von eigenem Avatar erlauben" name="alow_self_impostor" tool_tip="Falls aktiviert, kann der Viewer den eigenen Avatar als Impostor darstellen." />
<check_box label="Optimierte Renderzeit anzeigen" name="show_tuned_art" tool_tip="Falls aktiviert, wird in der Zeit-Spalte die aktuelle Renderzeit und nicht die Renderzeit vor Optimierung angezeigt." />
<text name="sundry_desc1">
Diese Optionen kontrollieren eher subtile Einstellungen. In der Online-Hilfe finden sich weitere Informationen darüber, was diese genau bedeuten.
</text>
</panel>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_performance_complexity">
<text name="back_lbl">
Zurück
</text>
<text name="attachments_title">
Avatar-Attachment-Komplexität
</text>
<text name="tot_att_count">
Gesamt: 50 (120000.10μs)
</text>
<text name="attachments_desc1">
Attachments machen den Avatar komplexer und langsamer zu rendern.
</text>
<text name="attachments_desc2">
Dieses Fenster zeigt alle Attachments des eigenen Avatars.
</text>
<text name="attachments_desc3">
Attachments können einfach ausgewählt und durch Klick auf „X“ entfernt werden.
</text>
<name_list name="obj_list">
<name_list.columns label="Zeit (μs)" name="art_value" tool_tip="Benötigte Zeit in Millisekunden zum Rendern des Attachments." />
<name_list.columns name="complex_value" tool_tip="Attachment-Komplexität (ARC)" />
<name_list.columns label="Attachment-Name" tool_tip="Zum Entfernen auf „X“ klicken." name="name" />
</name_list>
</panel>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_performance_huds">
<text name="back_lbl">
Zurück
</text>
<text name="huds_title">
Aktive HUDs
</text>
<text name="huds_desc1">
Das Entfernen unbenötigter HUDs spart Speicher und kann den Viewer schneller machen.
</text>
<text name="huds_desc2">
HUDs enthalten oftmals viele Skripte und erzeugen zudem Serverseitigen Lag.
</text>
<text name="huds_desc3">
Hinweis: Minimieren-Buttons von HUDs entfernt diese nicht. Entfernen duch Klick auf „X“.
</text>
<name_list name="hud_list">
<name_list.columns label="Zeit (μs)" name="art_value" tool_tip="Benötigte Zeit in Millisekunden zum Rendern des HUD." />
<name_list.columns label="Name" tool_tip="Zum Entfernen auf „X“ klicken." name="name" />
</name_list>
</panel>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_performance_nearby">
<text name="back_lbl">
Zurück
</text>
<text name="av_nearby_title">
Avatare in der Nähe
</text>
<text name="tot_av_count">
Gesamt: 50 (120000.10μs)
</text>
<text name="av_nearby_desc">
Komplexeste Avatare verstecken, um Geschwindigkeit zu erhören
</text>
<slider tool_tip="Definiert, aber welcher Komplexität ein Avatar als Impostor dargestellt wird" label="Max. Komplexität (K)" name="IndirectMaxComplexity" />
<slider tool_tip="Definiert, aber wann ein Avatar als zu komplex zum Darstellen erachtet wird (Einheit: Mikrosekunden)" label="Max. Renderzeit (μs)" name="FSRenderAvatarMaxART" />
<text name="FSRenderAvatarMaxARTText">
Kein Limit
</text>
<name_list name="nearby_list">
<name_list.columns tool_tip="Balkendiagram der benötigten Renderzeit (inkl. Auto-Anpassung) in Prozent, basierend auf dem Langsamsten." name="art_visual" />
<name_list.columns tool_tip="Avatar-Renderzeit (ART). Tatsächlich benötigte Zeit in Mikrosekunden für die Darstellung des Avatars vor Auto-Anpassung." name="art_value" />
<name_list.columns tool_tip="Avatar-Komplexität (ARC) basierend auf Standard-Berechnung." name="complex_value" />
<name_list.columns tool_tip="Zeigt Auto-Anpassung: I = Impostor, S = Kein Schatten." name="state" />
<name_list.columns label="Name" name="name"/>
</name_list>
<text name="av_nearby_desc2">
Per Rechts-Klick auf einen Avatar kann auch die Darstellung angepasst werden.
</text>
<button label="Ausnahmen..." name="exceptions_btn" />
<check_box label="Freunde immer komplett darstellen" name="display_friends" />
<check_box label="Alle Avatare verstecken (Gut für Landschaftsaufnahmen) " name="hide_avatars" />
<text name="name_tags_textbox">
Avatar namen:
</text>
<radio_group name="name_tag_mode">
<radio_item label="An" name="radio" />
<radio_item label="Aus" name="radio2" />
<radio_item label="Kurz anzeigen" name="radio3" />
</radio_group>
</panel>

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_performance_preferences">
<text name="back_lbl">
Zurück
</text>
<text name="settings_title">
Grafik-Einstellungen
</text>
<text name="quality_lbl">
Qualität vs. Geschwindigkeit
</text>
<text name="FasterText">
Schnell
</text>
<text name="BetterText">
Qualität
</text>
<text name="ShadersPrefText">
Niedrig
</text>
<text name="ShadersPrefText2">
Mittel
</text>
<text name="ShadersPrefText3">
Hoch
</text>
<text name="ShadersPrefText4">
Ultra
</text>
<text name="quality_desc">
Auswahl einer Voreinstellung setzt alle manuellen Anpassungen zurück.
</text>
<text name="distance_lbl">
Distanz Sichtbarkeit
</text>
<text name="faster_lbl">
Schnell
</text>
<text name="farther_lbl">
Weiter
</text>
<text name="distance_desc1">
Für bessere Performance niedrig halten, Erhöhen für weitere Sichtbarkeit.
</text>
<text name="environment_lbl">
Umgebung
</text>
<text name="enhancements_desc">
Reduzieren / Entfernen von Schatten kann die FPS deutlich erhöhren,
beeinflusst aber das Ambiente und Aussehen der Szenerie.
</text>
<text name="RenderShadowDetailText">
Schatten-Quellen:
</text>
<combo_box name="ShadowDetail">
<combo_box.item label="Keine" name="0" />
<combo_box.item label="Sonne/Mond" name="1" />
<combo_box.item label="Sonne/Mond + Projektoren" name="2" />
</combo_box>
<text name="water_lbl">
Wasser
</text>
<text name="water_desc">
Reduzieren der Wasser-Qualität kann die FPS deutlich erhöhen.
</text>
<text name="ReflectionsText">
Wasser-Reflektionen:
</text>
<combo_box name="Reflections">
<combo_box.item label="Keine (undurchsichtig)" name="-2" />
<combo_box.item label="Keine (transparent)" name="-1" />
<combo_box.item label="Minimal" name="0" />
<combo_box.item label="Terrain und Bäume" name="1" />
<combo_box.item label="Alle statischen Objekte" name="2" />
<combo_box.item label="Alle Avatare und Objekte" name="3" />
<combo_box.item label="Alles" name="4" />
</combo_box>
<text name="photo_lbl">
Fotografie
</text>
<text name="photo_desc">
Fotografen benötigen hohe Qualität, allerdings
häuftig auf Kosten der Performance. Fototools
können helfen, die richtige Balance zu finden.
</text>
<button name="open_phototools" label="Fototools" tool_tip="Öffnet dedizierte Fototools für fortgeschrittene Einstellungen." />
</panel>

View File

@ -5902,6 +5902,9 @@ Setzen Sie den Editorpfad in Anführungszeichen
<string name="Command_People_Label">
Leute
</string>
<string name="Command_Performance_Label">
Grafikgeschwindigkeit
</string>
<string name="Command_Picks_Label">
Auswahlen
</string>
@ -6104,6 +6107,9 @@ Setzen Sie den Editorpfad in Anführungszeichen
<string name="Command_People_Tooltip">
Freunde, Gruppen und Leute in der Nähe
</string>
<string name="Command_Performance_Tooltip">
Grafikgeschwindigkeit verbessern
</string>
<string name="Command_Picks_Tooltip">
Orte, die in Ihrem Profil als Favoriten angezeigt werden sollen
</string>

View File

@ -19,7 +19,7 @@
</floater.string>
<panel
background_opaque="false"
bg_alpha_color="AddPaymentPanel"
bg_alpha_color="PanelGray"
border_visible="false"
background_visible="true"
label="wrapper_panel"

View File

@ -10,7 +10,7 @@
save_rect="true"
single_instance="true"
reuse_instance="true"
title="AVATAR RENDER SETTINGS"
title="Avatar Display Exceptions"
width="300">
<string
name="av_never_render"
@ -18,53 +18,45 @@
<string
name="av_always_render"
value="Always"/>
<filter_editor
follows="left|top|right"
height="23"
layout="topleft"
left="8"
right="-47"
label="Filter People"
max_length_chars="300"
name="people_filter_input"
text_color="Black"
text_pad_left="10"
top="4" />
<menu_button
follows="top|right"
height="25"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="AddItem_Off"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
left_pad="7"
menu_filename="menu_avatar_rendering_settings_add.xml"
menu_position="bottomleft"
name="plus_btn"
tool_tip="Actions on selected person"
top="3"
width="31" />
<name_list
bottom="-8"
bottom="-33"
draw_heading="true"
follows="all"
left="8"
multi_select="false"
name="render_settings_list"
right="-8"
top="32">
top="0">
<name_list.columns
label="Name"
name="name"
relative_width="0.5" />
relative_width="0.65" />
<name_list.columns
label="Render setting"
label="Full detail"
name="setting"
relative_width="0.25" />
<name_list.columns
label="Date added"
name="timestamp"
relative_width="0.25" />
relative_width="0.35" />
</name_list>
<panel
bg_alpha_color="ScrollBgWriteableColor"
background_visible="true"
background_opaque="false"
bevel_style="none"
follows="bottom|left|right"
name="add_subpanel"
layout="topleft"
height="28"
top_pad="0">
<menu_button
follows="bottom|left"
height="25"
label="Add someone..."
layout="topleft"
menu_filename="menu_avatar_rendering_settings_add.xml"
menu_position="bottomleft"
name="plus_btn"
tool_tip="Actions on selected person"
top="1"
left="8"
width="120" />
</panel>
</floater>

View File

@ -2,7 +2,7 @@
<floater
name="avatarrendersettings"
help_topic="fs_avatar_render_settings"
title="Avatar Render Settings"
title="Avatar Display Exceptions"
min_width="350"
min_height="320"
width="450"
@ -18,7 +18,7 @@
Never
</floater.string>
<floater.string name="av_render_always">
Fully
Always
</floater.string>
<filter_editor
follows="left|top|right"
@ -66,7 +66,7 @@
label="Name"
name="name" />
<name_list.columns
label="Render Setting"
label="Full detail"
name="render_setting"
width="100" />
</name_list>

View File

@ -0,0 +1,514 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
height="652"
layout="topleft"
name="performance"
help_topic="fs_performance_floater"
save_rect="true"
title="Improve Graphics Speed (Experimental)"
can_resize="true"
min_height="652"
max_height="652"
min_width="580"
width="580">
<floater.string name="frame_stats">
Frame: [TOT_FRAME_TIME]ms - Scenery:[SCENERY_FRAME_PCT]% Avatars:[AV_FRAME_PCT]% UI:[UI_FRAME_PCT]% HUDS:[HUDS_FRAME_PCT]% SWAP:[SWAP_FRAME_PCT]% TASKS:[IDLE_FRAME_PCT]%
</floater.string>
<floater.string name="limit_fps">
FPS capped at [FPSCAP] fps
</floater.string>
<floater.string name="tuning_fps">
Auto Tune target [FPSTARGET] fps
</floater.string>
<floater.string name="av_frame_pct">
[AV_FRAME_PCT]%
</floater.string>
<floater.string name="huds_frame_pct">
[HUDS_FRAME_PCT]%
</floater.string>
<floater.string name="focus_fps">
In Background
</floater.string>
<floater.string name="tot_av_template">
Total: [TOT_AV] ([TOT_AV_TIME]μs)
</floater.string>
<floater.string name="tot_att_template">
Total: [TOT_ATT] ([TOT_ATT_TIME]μs)
</floater.string>
<panel
bevel_style="none"
follows="left|top|right"
height="600"
width="580"
name="panel_top"
visible="true"
layout="topleft"
left="0"
top="0">
<panel
bg_alpha_color="black"
background_visible="true"
background_opaque="false"
border="false"
bevel_style="none"
follows="left|top|right"
height="55"
width="560"
name="fps_subpanel"
layout="topleft"
left="10"
top="5">
<text
follows="left|top"
font="SansSerifHuge"
text_color="White"
height="20"
layout="topleft"
left="20"
top="8"
name="fps_value"
width="42">
167
</text>
<text
follows="left|top"
font="SansSerifLarge"
text_color="White"
height="20"
layout="topleft"
left_pad="3"
top="13"
name="fps_lbl"
width="150">
frames per second
</text>
<text
follows="left|top"
font="SansSerifLarge"
text_color="DrYellow"
height="28"
layout="topleft"
left_pad="10"
name="fps_warning"
top="13"
width="150">
</text>
<text
follows="top|right"
text_color="White"
height="40"
layout="topleft"
left="395"
top="5"
name="fps_desc1_lbl"
width="150"
wrap="true">
Allow 5-10 seconds for changes to take full effect.
</text>
<text
follows="left|top|right"
font="MonospaceMedium"
text_color="White"
height="20"
layout="topleft"
halign="center"
left="5"
top="38"
name="frame_breakdown"
width="550">
[--------------------Frame breakdown will appear here.---------------------]
</text>
</panel>
<panel
bg_alpha_color="black"
background_visible="true"
background_opaque="false"
border="false"
bevel_style="none"
follows="left|top|right"
height="55"
width="560"
name="target_subpanel"
layout="topleft"
left="10"
top_pad="0">
<text
follows="left|top"
font="SansSerifLarge"
text_color="White"
height="20"
layout="topleft"
left="10"
name="settings_lbl"
top="7"
width="240">
Auto-Tune Frame Rate
</text>
<check_box
control_name="FSAutoTuneFPS"
follows="top|right"
height="16"
initial_value="false"
label="Auto tune for FPS"
layout="topleft"
left_pad="40"
name="AutoTuneFPS"
top_delta="0"
tool_tip="The viewer will attempt to adjust settings to meet the target FPS."
width="50">
</check_box>
<text
follows="left|top"
font="SansSerif"
text_color="White"
height="20"
layout="topleft"
left="10"
name="settings_desc"
top_pad="3"
width="275">
Automatically adjust settings to maintain FPS
</text>
<combo_box
follows="top|right"
font="SansSerif"
text_color="White"
height="20"
layout="topleft"
left_pad="5"
control_name="FSTuningFPSStrategy"
name="FSTuningFPSStrategy"
top_delta="0"
width="150">
<combo_box.item
label="Tune Avatars Only"
name="av_only"
value="0" />
<combo_box.item
label="Avatar and scene"
name="av_and_scene"
value="1" />
</combo_box>
<spinner
name="target_fps"
control_name="FSTargetFPS"
font="SansSerifLarge"
tooltip="Target FPS - The desired FPS level. The viewer will attempt to achieve this by adjusting your graphics settings."
layout="topleft"
follows="right|top"
right="-55"
top_pad="-32"
height="40"
visible="true"
decimal_digits="0"
increment="1"
initial_value="25"
max_val="200"
min_val="1"
width="40"
label="" />
<button
height="16"
width="16"
layout="topleft"
mouse_opaque="true"
follows="right|top"
name="target_btn"
top="19"
image_selected="Icon_Gear"
image_pressed="Icon_Gear"
image_unselected="Icon_Gear"
right="-20"
is_toggle="true">
</button>
</panel>
</panel>
<panel
bevel_style="none"
follows="left|top|right"
height="540"
width="580"
name="panel_performance_main"
visible="true"
layout="topleft"
left="0"
top="115">
<panel
bg_alpha_color="PanelGray"
background_visible="true"
background_opaque="false"
border="true"
bevel_style="none"
follows="left|top|right"
height="50"
width="560"
name="settings_subpanel"
layout="topleft"
left="10"
top_pad="10">
<text
follows="left|top"
font="SansSerifLarge"
text_color="White"
height="20"
layout="topleft"
left="10"
name="settings_lbl"
top="7"
width="180">
Graphics settings
</text>
<text
follows="left|top"
font="SansSerif"
text_color="White"
height="20"
layout="topleft"
left="10"
name="settings_desc"
top_pad="0"
width="395">
Choose settings for distance, water, lighting and more.
</text>
<icon
height="16"
width="16"
image_name="Arrow_Right_Off"
mouse_opaque="true"
name="icon_arrow3"
follows="right|top"
top="19"
right="-20"/>
</panel>
<panel
bg_alpha_color="PanelGray"
background_visible="true"
background_opaque="false"
border="true"
bevel_style="none"
follows="left|top|right"
height="50"
width="560"
name="nearby_subpanel"
layout="topleft"
top_pad="10">
<text
follows="left|top"
font="SansSerifLarge"
text_color="White"
height="20"
layout="topleft"
left="10"
name="avatars_nearby_lbl"
top="7"
width="205">
Avatars nearby
</text>
<text
follows="left|top"
font="SansSerif"
text_color="White"
height="20"
layout="topleft"
left="10"
name="avatars_nearby_desc"
top_pad="0"
width="345">
Manage which nearby avatars are fully displayed.
</text>
<text
follows="top|right"
font="SansSerifSmall"
text_color="White"
height="28"
layout="topleft"
left_pad="10"
name="avatars_frme_pct_lbl"
top="8"
width="75">
Time spent
drawing
avatars
</text>
<text
follows="top|right"
font="SansSerifHuge"
text_color="White"
height="20"
layout="topleft"
left_pad="10"
top="14"
name="av_frame_stats"
width="62">
00%
</text>
<icon
height="16"
width="16"
image_name="Arrow_Right_Off"
mouse_opaque="true"
name="icon_arrow2"
follows="right|top"
top="19"
right="-20"/>
</panel>
<panel
bg_alpha_color="PanelGray"
background_visible="true"
background_opaque="false"
border="true"
bevel_style="none"
follows="left|top|right"
height="50"
width="560"
name="complexity_subpanel"
layout="topleft"
top_pad="10">
<text
follows="left|top"
font="SansSerifLarge"
text_color="White"
height="20"
layout="topleft"
left="10"
name="complexity_lbl"
top="7"
width="180">
Your avatar complexity
</text>
<text
follows="left|top"
font="SansSerif"
text_color="White"
height="20"
layout="topleft"
left="10"
name="complexity_info"
top_pad="0"
width="455">
Be a good citizen. Manage the impact of your avatar
</text>
<icon
height="16"
width="16"
image_name="Arrow_Right_Off"
mouse_opaque="true"
name="icon_arrow4"
follows="right|top"
top="19"
right="-20"/>
</panel>
<panel
bg_alpha_color="PanelGray"
background_visible="true"
background_opaque="false"
border="true"
bevel_style="none"
follows="left|top|right"
height="50"
width="560"
name="huds_subpanel"
layout="topleft"
top_pad="10">
<text
follows="left|top"
font="SansSerifLarge"
text_color="White"
height="20"
layout="topleft"
left="10"
name="huds_lbl"
top="7"
width="135">
Your active HUDs
</text>
<text
follows="left|top"
font="SansSerif"
text_color="White"
height="20"
layout="topleft"
left="10"
name="huds_desc"
top_pad="0"
width="345">
Removing unnecessary HUDs may improve speed.
</text>
<text
follows="top|right"
font="SansSerifSmall"
text_color="White"
height="28"
layout="topleft"
left_pad="10"
name="huds_frme_pct_lbl"
top="8"
width="75">
Time spent
drawing
HUDs
</text>
<text
follows="top|right"
font="SansSerifHuge"
text_color="White"
height="20"
layout="topleft"
left_pad="10"
top="14"
name="huds_frame_stats"
width="62">
00%
</text>
<icon
height="16"
width="16"
image_name="Arrow_Right_Off"
mouse_opaque="true"
name="icon_arrow4"
follows="right|top"
top="19"
right="-20"/>
</panel>
</panel>
<panel
filename="panel_performance_nearby.xml"
follows="all"
layout="topleft"
left="0"
name="panel_performance_nearby"
visible="false"
top="115" />
<panel
filename="panel_performance_complexity.xml"
follows="all"
layout="topleft"
left="0"
name="panel_performance_complexity"
visible="false"
top="115" />
<panel
filename="panel_performance_preferences.xml"
follows="all"
layout="topleft"
left="0"
name="panel_performance_preferences"
visible="false"
top="115" />
<panel
filename="panel_performance_huds.xml"
follows="all"
layout="topleft"
left="0"
name="panel_performance_huds"
visible="false"
top="115" />
<panel
filename="panel_performance_autotune.xml"
follows="all"
layout="topleft"
left="0"
name="panel_performance_autotune"
visible="false"
top="115" />
</floater>

View File

@ -6,7 +6,7 @@
help_topic="Preferences_Graphics_Advanced"
single_instance="true"
save_rect="true"
title="ADVANCED GRAPHICS PREFERENCES"
title="Advanced Graphics Preferences"
width="800">
<!-- This block shows Advanced Settings -->

View File

@ -169,18 +169,18 @@
<menu_item_separator />
<menu_item_check
name="RenderNormally"
label="Render Normally">
name="AlwaysRenderFully"
label="Always Display Full Detail">
<menu_item_check.on_check
function="Avatar.CheckImpostorMode"
parameter="0" />
parameter="2" />
<menu_item_check.on_click
function="Avatar.SetImpostorMode"
parameter="0" />
parameter="2" />
</menu_item_check>
<menu_item_check
name="DoNotRender"
label="Do Not Render">
label="Never Display Full Detail">
<menu_item_check.on_check
function="Avatar.CheckImpostorMode"
parameter="1" />
@ -189,14 +189,14 @@
parameter="1" />
</menu_item_check>
<menu_item_check
name="AlwaysRenderFully"
label="Render Fully">
<menu_item_check.on_check
name="RenderNormally"
label="Remove From Display Exceptions">
<menu_item_check.on_visible
function="Avatar.CheckImpostorMode"
parameter="2" />
parameter="4" />
<menu_item_check.on_click
function="Avatar.SetImpostorMode"
parameter="2" />
parameter="0" />
</menu_item_check>
<menu_item_call

View File

@ -197,18 +197,18 @@
<menu_item_separator />
<menu_item_check
name="RenderNormally"
label="Render Normally">
name="AlwaysRenderFully"
label="Always Display Full Detail">
<menu_item_check.on_check
function="Avatar.CheckImpostorMode"
parameter="0" />
parameter="2" />
<menu_item_check.on_click
function="Avatar.SetImpostorMode"
parameter="0" />
parameter="2" />
</menu_item_check>
<menu_item_check
name="DoNotRender"
label="Do Not Render">
label="Never Display Full Detail">
<menu_item_check.on_check
function="Avatar.CheckImpostorMode"
parameter="1" />
@ -217,14 +217,14 @@
parameter="1" />
</menu_item_check>
<menu_item_check
name="AlwaysRenderFully"
label="Render Fully">
<menu_item_check.on_check
name="RenderNormally"
label="Remove From Display Exceptions">
<menu_item_check.on_visible
function="Avatar.CheckImpostorMode"
parameter="2" />
parameter="4" />
<menu_item_check.on_click
function="Avatar.SetImpostorMode"
parameter="2" />
parameter="0" />
</menu_item_check>
<menu_item_call

View File

@ -3,24 +3,25 @@
layout="topleft"
name="Settings">
<menu_item_check
label="Default"
layout="topleft"
name="default">
<on_click function="Settings.SetRendering" parameter="default"/>
<on_check function="Settings.IsSelected" parameter="default" />
</menu_item_check>
<menu_item_check
label="Always render"
label="Always full detail"
layout="topleft"
name="always_render">
<on_click function="Settings.SetRendering" parameter="always"/>
<on_check function="Settings.IsSelected" parameter="always" />
<on_check function="Settings.IsSelected" parameter="always" />
</menu_item_check>
<menu_item_check
label="Never render"
label="Never full detail"
layout="topleft"
name="never_render">
<on_click function="Settings.SetRendering" parameter="never"/>
<on_check function="Settings.IsSelected" parameter="never" />
</menu_item_check>
<on_check function="Settings.IsSelected" parameter="never" />
</menu_item_check>
<menu_item_check
label="Remove from exceptions"
layout="topleft"
name="default">
<on_click function="Settings.SetRendering" parameter="default"/>
<on_check function="Settings.IsSelected" parameter="default" />
<on_visible function="Settings.IsSelected" parameter="non_default" />
</menu_item_check>
</context_menu>

View File

@ -4,13 +4,13 @@
left="0" bottom="0" visible="false"
mouse_opaque="false">
<menu_item_call
label="Always Render a Resident..."
label="Always full detail..."
name="add_avatar_always_render">
<on_click
function="Settings.AddNewEntry" parameter="always"/>
</menu_item_call>
<menu_item_call
label="Never Render a Resident..."
label="Never full detail..."
name="add_avatar_never_render">
<on_click
function="Settings.AddNewEntry" parameter="never"/>

View File

@ -3,15 +3,15 @@
layout="topleft"
name="Avatar Render Settings Menu">
<menu_item_call
label="Render Normally (removes from list)"
label="Always Full Detail"
layout="topleft"
name="av_render_normal">
name="av_render_always">
<menu_item_call.on_click
function="Avatar.ChangeRenderSetting"
parameter="0" />
parameter="2" />
</menu_item_call>
<menu_item_call
label="Do Not Render"
label="Never Full Detail"
layout="topleft"
name="av_render_never">
<menu_item_call.on_click
@ -19,11 +19,11 @@
parameter="1" />
</menu_item_call>
<menu_item_call
label="Render Fully"
label="Remove From Exceptions"
layout="topleft"
name="av_render_always">
name="av_render_normal">
<menu_item_call.on_click
function="Avatar.ChangeRenderSetting"
parameter="2" />
parameter="0" />
</menu_item_call>
</context_menu>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<context_menu
layout="topleft"
name="Settings">
<menu_item_check
label="Always full detail"
layout="topleft"
name="always_render">
<on_click function="Settings.SetRendering" parameter="always"/>
<on_check function="Settings.IsSelected" parameter="always" />
</menu_item_check>
<menu_item_check
label="Never full detail"
layout="topleft"
name="never_render">
<on_click function="Settings.SetRendering" parameter="never"/>
<on_check function="Settings.IsSelected" parameter="never" />
</menu_item_check>
<menu_item_check
label="Remove from exceptions"
layout="topleft"
name="default">
<on_click function="Settings.SetRendering" parameter="default"/>
<on_check function="Settings.IsSelected" parameter="default" />
<on_visible function="Settings.IsSelected" parameter="non_default" />
</menu_item_check>
<menu_item_separator />
<menu_item_call
label="Inspect Avatar"
name="inspect">
<menu_item_call.on_click
function="Avatar.Extended" parameter="inspect"/>
</menu_item_call>
<menu_item_call
label="Zoom to Avatar"
tool_tip="Move camera to view this avatar."
name="zoom">
<menu_item_call.on_click
function="Avatar.Extended" parameter="zoom"/>
</menu_item_call>
</context_menu>

View File

@ -221,13 +221,16 @@
</pie_menu>
<pie_menu
name="RenderMenu"
label="Render &gt;">
label="Display &gt;">
<pie_slice
name="RenderNormally"
label="Normally">
<pie_slice.on_click
function="Avatar.SetImpostorMode"
parameter="0" />
<pie_slice.on_visible
function="Avatar.CheckImpostorMode"
parameter="4" />
</pie_slice>
<pie_slice
name="DoNotRender"

View File

@ -195,13 +195,16 @@
</pie_slice>
<pie_menu
name="RenderMenu"
label="Render &gt;">
label="Display &gt;">
<pie_slice
name="RenderNormally"
label="Normally">
<pie_slice.on_click
function="Avatar.SetImpostorMode"
parameter="0" />
<pie_slice.on_visible
function="Avatar.CheckImpostorMode"
parameter="4" />
</pie_slice>
<pie_slice
name="DoNotRender"

View File

@ -1198,7 +1198,16 @@
parameter="UseDebugMenus" />
</menu_item_check>
</menu>
<menu_item_check
label="Improve graphics speed..."
name="Performance">
<menu_item_check.on_click
function="Floater.Toggle"
parameter="performance" />
<menu_item_check.on_check
function="Floater.Visible"
parameter="performance" />
</menu_item_check>
<menu_item_separator/>
<menu_item_call

View File

@ -0,0 +1,230 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
bevel_style="none"
follows="left|top"
height="530"
width="580"
name="panel_performance_autotune"
layout="topleft"
left="0"
top="0">
<button
height="16"
width="16"
layout="topleft"
mouse_opaque="true"
follows="left|top"
name="back_btn"
top="7"
image_selected="Arrow_Left_Off"
image_pressed="Arrow_Left_Off"
image_unselected="Arrow_Left_Off"
left="15"
is_toggle="true">
</button>
<text
follows="left|top"
height="20"
layout="topleft"
left_pad="3"
top="10"
name="back_lbl"
width="40">
Back
</text>
<text
follows="left|top"
font="SansSerifLarge"
text_color="white"
height="20"
layout="topleft"
left="20"
top_pad="10"
name="settings_title"
width="300">
Auto Tune Preferences
</text>
<view_border
bevel_style="in"
height="0"
layout="topleft"
name="border1"
left="20"
top_pad="8"
width="540" />
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="40"
layout="topleft"
top_pad="20"
left="20"
name="quality_lbl"
width="100"
wrap="true">
Distant Avatars
</text>
<check_box
control_name="FSAutoTuneImpostorByDistEnabled"
height="19"
label="Enable distance based optimization"
layout="topleft"
follows="top|left"
left_pad="40"
name="FSAutoTuneImpostorByDistEnabled"
tool_tip="When enabled the viewer will adjust the MaxNonImpostors setting to limit fully rendered avatars to those within the defined radius."
top_delta="0"
width="190"
label_wrap="true" />
<spinner
control_name="FSAutoTuneImpostorFarAwayDistance"
height="20"
layout="topleft"
label="Farthest full avatar"
label_width="80"
label_wrap="true"
follows="top|left"
name="ffa_autotune"
left_pad="40"
decimal_digits="2"
min_val="16"
max_val="256"
width="140" >
</spinner>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="28"
layout="topleft"
top_pad="15"
left="160"
name="distant_av_advice"
width="450">
Avatars that are further away still have a high impact.
Set the distance from camera beyond which an avatar will be optimized.
</text>
<view_border
bevel_style="in"
height="0"
layout="topleft"
name="border2"
top_pad="8"
left="20"
width="540" />
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="36"
layout="topleft"
top_pad="20"
left="20"
name="distance_lbl"
width="100"
wrap="true">
Visibility distance tuning limits
</text>
<spinner
control_name="FSAutoTuneRenderFarClipMin"
height="20"
layout="topleft"
label="Minimum Distance"
label_width="80"
label_wrap="true"
top_delta="0"
follows="top|left"
name="min_dd_autotune"
decimal_digits="2"
left_pad="40"
min_val="32"
max_val="256"
width="140">
</spinner>
<spinner
control_name="FSAutoTuneRenderFarClipTarget"
height="20"
layout="topleft"
label="Preferred distance"
label_width="80"
label_wrap="true"
follows="top|left"
name="pref_dd_autotune"
left_pad="20"
min_val="32"
max_val="256"
width="140">
</spinner>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="38"
layout="topleft"
top_pad="15"
left="160"
name="distance_desc1"
wrap="true"
width="400">
When adjusting scene parameters, autotune will optimize draw distance to between the minimum and the preferred.
</text>
<view_border
bevel_style="in"
height="0"
layout="topleft"
name="border2"
top_pad="8"
left="20"
width="540" />
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="36"
layout="topleft"
top_pad="20"
left="20"
name="sundry_lbl"
width="100"
wrap="true">
Sundry Settings
</text>
<check_box
control_name="FSAllowSelfImpostor"
height="19"
label="Allow your own avatar to be optimized"
layout="topleft"
follows="top|left"
left_pad="40"
name="alow_self_impostor"
tool_tip="When enabled the viewer may render your own avatar as an impostor."
top_delta="0"
width="190"
label_wrap="true" />
<check_box
control_name="FSShowTunedART"
height="19"
label="Show optimized render time"
layout="topleft"
follows="top|left"
left_delta="0"
name="show_tuned_art"
tool_tip="When enabled the Time column shows the current render time not the pre-tuning render time."
top_pad="0"
width="190"
label_wrap="true" />
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="38"
layout="topleft"
top_pad="15"
left="160"
name="sundry_desc1"
wrap="true"
width="400">
These options control more subtle settings. Use the online help page to get more information on what these do.
</text>
</panel>

View File

@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel bevel_style="none"
follows="left|top"
height="530"
width="580"
name="panel_performance_complexity"
layout="topleft"
left="0"
top="0">
<button height="16"
width="16"
layout="topleft"
mouse_opaque="true"
follows="left|top"
name="back_btn"
top="7"
image_selected="Arrow_Left_Off"
image_pressed="Arrow_Left_Off"
image_unselected="Arrow_Left_Off"
left="15"
is_toggle="true">
</button>
<text follows="left|top"
height="20"
layout="topleft"
left_pad="3"
top="10"
name="back_lbl"
width="40">
Back
</text>
<text follows="left|top"
font="SansSerifLarge"
text_color="white"
height="20"
layout="topleft"
left="20"
top_pad="10"
name="attachments_title"
width="250">
Avatar attachment complexity
</text>
<text follows="right|top"
font="SansSerifLarge"
text_color="White"
height="20"
layout="topleft"
right="-40"
top_delta="0"
name="tot_att_count"
halign="right"
width="200">
Total: 50 (120000.10μs)
</text>
<text follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
top_pad="5"
left="20"
name="attachments_desc1"
width="580">
Attachments make your avatar more complex and slower to render.
</text>
<text follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
top_pad="3"
left="20"
name="attachments_desc2"
width="580">
This screen allows you to view the attachments of your own avatar.
</text>
<text follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
top_pad="3"
left="20"
name="attachments_desc3"
width="580">
You may remove your own attachments quickly and easily by hitting the 'X'.
</text>
<name_list left="20"
column_padding="1"
draw_stripes="true"
draw_heading="true"
height="379"
follows="left|top"
sort_column="1"
sort_ascending="false"
multi_select="false"
layout="topleft"
name="obj_list"
top_pad="10"
width="540">
<name_list.columns label=""
name="art_visual"
width="90" />
<name_list.columns label="Time (μs)"
name="art_value"
tool_tip="Time taken to render this attachment (microseconds)"
width="80" />
<name_list.columns label="ARC"
name="complex_value"
tool_tip="Item complexity (ARC)"
width="40" />
<name_list.columns label="Attachment name"
tool_tip="Click the 'X' to detach"
name="name" />
</name_list>
</panel>

View File

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel bevel_style="none"
follows="left|top"
height="530"
width="580"
name="panel_performance_huds"
layout="topleft"
left="0"
top="0">
<button height="16"
width="16"
layout="topleft"
mouse_opaque="true"
follows="left|top"
name="back_btn"
top="7"
image_selected="Arrow_Left_Off"
image_pressed="Arrow_Left_Off"
image_unselected="Arrow_Left_Off"
left="15"
is_toggle="true">
</button>
<text follows="left|top"
height="20"
layout="topleft"
left_pad="3"
top="10"
name="back_lbl"
width="40">
Back
</text>
<text follows="left|top"
font="SansSerifLarge"
text_color="White"
height="20"
layout="topleft"
left="20"
top_pad="10"
name="huds_title"
width="135">
Your active HUDs
</text>
<text follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
top_pad="5"
left="20"
name="huds_desc1"
width="540">
Detaching HUDs you aren't using saves memory and can make the viewer run faster.
</text>
<text follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
top_pad="3"
left="20"
name="huds_desc2"
width="540">
HUDs are often heavily scripted and also contribute to server-side lag.
</text>
<text follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
top_pad="3"
left="20"
name="huds_desc3"
width="540">
Note: Using a HUD's minimize button does not detach it. Use the X to remove it.
</text>
<name_list
column_padding="1"
draw_stripes="true"
draw_heading="true"
height="380"
follows="left|top"
layout="topleft"
name="hud_list"
top_pad="10"
width="540">
<name_list.columns
label=""
name="art_visual"
width="90" />
<name_list.columns
label="Time (μs)"
name="art_value"
tool_tip="Time taken to render this HUD (microseconds)"
width="80" />
<name_list.columns
label="Name"
tool_tip="Click the 'X' to detach"
name="name" />
</name_list>
</panel>

View File

@ -0,0 +1,273 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
bevel_style="none"
follows="left|top|right"
height="530"
width="580"
name="panel_performance_nearby"
layout="topleft"
left="0"
top="0">
<button
height="16"
width="16"
layout="topleft"
mouse_opaque="true"
follows="left|top"
name="back_btn"
top="7"
image_selected="Arrow_Left_Off"
image_pressed="Arrow_Left_Off"
image_unselected="Arrow_Left_Off"
left="15"
is_toggle="true">
</button>
<text
follows="left|top"
height="20"
layout="topleft"
left_pad="3"
top="10"
name="back_lbl"
width="40">
Back
</text>
<text
follows="left|top"
font="SansSerifLarge"
text_color="White"
height="20"
layout="topleft"
left="20"
top_pad="10"
name="av_nearby_title"
width="205">
Avatars nearby</text>
<text
follows="right|top"
font="SansSerifLarge"
text_color="White"
height="20"
layout="topleft"
right="-40"
top_delta="0"
name="tot_av_count"
halign="right"
width="200">
Total: 50 (120000.10μs)
</text>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
left="20"
top_pad="5"
name="av_nearby_desc"
width="580">
Hide the most complex avatars to boost speed.
</text>
<slider
control_name="IndirectMaxComplexity"
visible="false"
tool_tip="Controls at what point a visually complex avatar is drawn as a Impostor"
follows="left|top"
height="16"
initial_value="101"
increment="1"
label="Maximum complexity (K)"
text_color="White"
label_width="165"
layout="topleft"
min_val="1"
max_val="101"
name="IndirectMaxComplexity"
show_text="false"
top_pad="10"
width="300">
</slider>
<text
type="string"
visible="false"
length="1"
follows="left|top"
height="16"
layout="topleft"
top_delta="0"
left_delta="304"
text_color="White"
name="IndirectMaxComplexityText"
width="65">
0
</text>
<slider
control_name="FSRenderAvatarMaxART"
tool_tip="Controls when a visually complex avatar is considered to be taking too long to render (unit: microseconds)"
follows="left|top"
height="16"
initial_value="4.7"
increment="0.01"
label="Maximum render time (μs)"
text_color="White"
label_width="165"
layout="topleft"
min_val="2"
max_val="4.7"
name="FSRenderAvatarMaxART"
show_text="false"
left_delta="-304"
top_delta="-16"
width="490">
</slider>
<text
type="string"
length="1"
follows="left|top"
height="16"
layout="topleft"
top_delta="0"
left_pad="5"
text_color="White"
name="FSRenderAvatarMaxARTText"
width="65">
no limit
</text>
<name_list
column_padding="1"
draw_stripes="true"
draw_heading="true"
height="280"
left="20"
follows="left|top|right"
layout="topleft"
sort_column="art_value"
short_names="true"
name="nearby_list"
name_column="name"
top_pad="10"
width="540">
<name_list.columns
label=""
tool_tip="Bar graph showing current render time (includes auto-tuning) as % of slowest."
name="art_visual"
width="90" />
<name_list.columns
label="Time (μs)"
tool_tip="Avatar Render Time. Actual time taken to render this avatar before any auto-tuning (in microseconds)."
name="art_value"
width="80" />
<name_list.columns
label="ARC"
tool_tip="Complexity (ARC) based on standard rules."
name="complex_value"
width="40" />
<name_list.columns
label=""
tool_tip="Shows any tuning. I=Impostor, S=no shadow."
name="state"
width="15" />
<name_list.columns
label="Name"
name="name"/>
</name_list>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
left="20"
top_pad="10"
name="av_nearby_desc2"
width="580">
You can also right-click on an avatar in-world to control display.
</text>
<button
height="23"
label="Exceptions..."
layout="topleft"
left="460"
top_delta="2"
name="exceptions_btn"
width="100">
</button>
<check_box
control_name="AlwaysRenderFriends"
height="16"
initial_value="true"
label="Always display friends in full detail"
label_text.text_color="White"
layout="topleft"
name="display_friends"
top_pad="3"
left="18"
width="256">
</check_box>
<view_border
bevel_style="in"
height="0"
layout="topleft"
name="border"
top_pad="15"
left="20"
width="540"/>
<check_box
height="16"
initial_value="true"
label="Hide avatars completely."
layout="topleft"
name="hide_avatars"
top_delta="15"
left="18"
width="280">
</check_box>
<text
type="string"
length="1"
follows="left|top"
height="15"
layout="topleft"
left="20"
name="name_tags_textbox"
top_pad="10"
width="400">
Name tags:
</text>
<radio_group
control_name="AvatarNameTagMode"
height="20"
layout="topleft"
left="120"
top_delta="0"
name="name_tag_mode">
<radio_item
label="Off"
name="radio"
top_delta="20"
layout="topleft"
height="16"
left="0"
value="0"
width="75" />
<radio_item
label="On"
left_pad="0"
layout="topleft"
top_delta="0"
height="16"
name="radio2"
value="1"
width="75" />
<radio_item
label="Show briefly"
left_pad="0"
name="radio3"
height="16"
layout="topleft"
top_delta="0"
value="2"
width="160" />
</radio_group>
</panel>

View File

@ -0,0 +1,518 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
bevel_style="none"
follows="left|top"
height="530"
width="580"
name="panel_performance_preferences"
layout="topleft"
left="0"
top="0">
<button
height="16"
width="16"
layout="topleft"
mouse_opaque="true"
follows="left|top"
name="back_btn"
top="7"
image_selected="Arrow_Left_Off"
image_pressed="Arrow_Left_Off"
image_unselected="Arrow_Left_Off"
left="15"
is_toggle="true">
</button>
<text
follows="left|top"
height="20"
layout="topleft"
left_pad="3"
top="10"
name="back_lbl"
width="40">
Back
</text>
<text
follows="left|top"
font="SansSerifLarge"
text_color="white"
height="20"
layout="topleft"
left="20"
top_pad="10"
name="settings_title"
width="300">
Graphics settings
</text>
<view_border
bevel_style="in"
height="0"
layout="topleft"
name="border1"
left="20"
top_pad="8"
width="540"/>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="36"
layout="topleft"
top_pad="20"
left="20"
name="quality_lbl"
width="100"
wrap="true">
Quality vs speed
</text>
<text
type="string"
length="1"
follows="left|top"
height="12"
layout="topleft"
left_pad="40"
name="FasterText"
top_delta="0"
width="40">
Faster
</text>
<icon
color="Slidermark"
height="14"
image_name="Rounded_Square"
layout="topleft"
left_delta="48"
name="LowGraphicsDivet"
top_delta="-2"
width="2" />
<icon
color="Slidermark"
height="14"
image_name="Rounded_Square"
layout="topleft"
left_pad="41"
name="LowMidGraphicsDivet"
top_delta="0"
width="2" />
<icon
color="Slidermark"
height="14"
image_name="Rounded_Square"
layout="topleft"
left_pad="41"
name="MidGraphicsDivet"
top_delta="0"
width="2" />
<icon
color="Slidermark"
height="14"
image_name="Rounded_Square"
layout="topleft"
left_pad="41"
name="MidHighGraphicsDivet"
top_delta="0"
width="2" />
<icon
color="Slidermark"
height="14"
image_name="Rounded_Square"
layout="topleft"
left_pad="41"
name="HighGraphicsDivet"
top_delta="0"
width="2" />
<icon
color="Slidermark"
height="14"
image_name="Rounded_Square"
layout="topleft"
left_pad="41"
name="HighUltraGraphicsDivet"
top_delta="0"
width="2" />
<icon
color="Slidermark"
height="14"
image_name="Rounded_Square"
layout="topleft"
left_pad="41"
name="UltraGraphicsDivet"
top_delta="0"
width="2" />
<text
type="string"
length="1"
follows="left|top"
height="12"
layout="topleft"
left_delta="20"
name="BetterText"
top_delta="0"
width="100">
Better Quality
</text>
<slider
control_name="RenderQualityPerformance"
decimal_digits="0"
follows="left|top"
height="16"
increment="1"
initial_value="0"
layout="topleft"
left_delta="-285"
max_val="6"
name="QualityPerformanceSelection"
show_text="false"
top_delta="-1"
width="275">
<slider.commit_callback
function="Pref.QualityPerformance"/>
</slider>
<text
type="string"
length="1"
follows="left|top"
halign="center"
height="12"
layout="topleft"
left="190"
name="ShadersPrefText"
top_delta="20"
width="80">
Low
</text>
<text
type="string"
length="1"
follows="left|top"
halign="center"
height="12"
layout="topleft"
left_delta="87"
name="ShadersPrefText2"
top_delta="0"
width="80">
Mid
</text>
<text
type="string"
length="1"
follows="left|top"
halign="center"
height="12"
layout="topleft"
left_delta="87"
name="ShadersPrefText3"
top_delta="0"
width="80">
High
</text>
<text
type="string"
length="1"
follows="left|top"
halign="center"
height="12"
layout="topleft"
left_delta="85"
name="ShadersPrefText4"
top_delta="0"
width="80">
Ultra
</text>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
top_pad="15"
left="160"
name="quality_desc"
width="450">
Choosing a preset will reset all manual changes you have made.
</text>
<view_border
bevel_style="in"
height="0"
layout="topleft"
name="border2"
top_pad="5"
left="20"
width="540"/>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="36"
layout="topleft"
top_pad="20"
left="20"
name="distance_lbl"
width="100"
wrap="true">
Visibility distance
</text>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
left_pad="40"
name="faster_lbl"
width="40"
top_delta="0">
Faster
</text>
<slider
control_name="RenderFarClip"
decimal_digits="0"
follows="left|top"
top_delta="-1"
height="16"
increment="8"
initial_value="160"
label_width="90"
slider_label.halign="right"
layout="topleft"
min_val="32"
max_val="1024"
name="draw_distance"
left_pad="5"
width="310" />
<text
type="string"
length="1"
follows="left|top"
height="12"
layout="topleft"
left_pad="-8"
top_delta="0"
name="draw_distance_m"
width="20">
m
</text>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
left_pad="0"
top_delta="1"
name="farther_lbl"
width="40">
Farther
</text>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
top_pad="15"
left="160"
name="distance_desc1"
width="450">
Keep this low for better performance, increase it to see further afield.
</text>
<view_border
bevel_style="in"
height="0"
layout="topleft"
name="border3"
top_pad="5"
left="20"
width="540"/>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
top_pad="20"
left="20"
name="environment_lbl"
width="100">
Environment
</text>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
top_delta="0"
left="160"
name="enhancements_desc"
width="450">
Reducing / eliminating shadows can be a boost to FPS but impacts
the ambience and appearance of the scene.
</text>
<text
type="string"
length="1"
follows="left|top"
height="16"
layout="topleft"
left="160"
name="RenderShadowDetailText"
text_readonly_color="LabelDisabledColor"
top_pad="20"
width="128">
Shadow sources:
</text>
<combo_box
control_name="RenderShadowDetail"
height="18"
layout="topleft"
right="-20"
top_delta="0"
name="ShadowDetail"
width="150">
<combo_box.item
label="None"
name="0"
value="0"/>
<combo_box.item
label="Sun/Moon"
name="1"
value="1"/>
<combo_box.item
label="Sun/Moon + Projectors"
name="2"
value="2"/>
</combo_box>
<view_border
bevel_style="in"
height="0"
layout="topleft"
name="border3"
top_pad="7"
left="20"
width="540"/>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
top_pad="20"
left="20"
name="water_lbl"
width="100">
Water
</text>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
top_delta="0"
left="160"
name="water_desc"
width="450">
Reducing water effects quality can greatly improve frame rate.
</text>
<text
type="string"
length="1"
follows="left|top"
height="16"
layout="topleft"
name="ReflectionsText"
text_readonly_color="LabelDisabledColor"
top_pad="16"
left="160"
width="128">
Water Reflections:
</text>
<combo_box
control_name="RenderReflectionDetail"
height="18"
layout="topleft"
right="-20"
top_delta="0"
name="Reflections"
width="150">
<combo_box.item
label="None; opaque"
name="-2"
value="-2"/>
<combo_box.item
label="None; transparent"
name="-1"
value="-1"/>
<combo_box.item
label="Minimal"
name="0"
value="0"/>
<combo_box.item
label="Terrain and trees"
name="1"
value="1"/>
<combo_box.item
label="All static objects"
name="2"
value="2"/>
<combo_box.item
label="All avatars and objects"
name="3"
value="3"/>
<combo_box.item
label="Everything"
name="4"
value="4"/>
</combo_box>
<view_border
bevel_style="in"
height="0"
layout="topleft"
name="border4"
top_pad="7"
left="20"
width="540"/>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="18"
layout="topleft"
top_pad="20"
left="20"
name="photo_lbl"
width="100">
Photography
</text>
<text
follows="left|top"
font="SansSerifSmall"
text_color="White"
height="48"
layout="topleft"
top_delta="0"
left="160"
name="photo_desc"
width="350">
Photographers need high quality, but this is often
at the cost of frame rate. [APP_NAME] phototools can
help you find the right balance.
</text>
<button
name="open_phototools"
label="Phototools"
tool_tip="Open the dedicated photo tools for advanced photo settings."
top_delta="0"
right="-20"
height="23"
width="120"
follows="bottom|right"
layout="topleft">
<button.init_callback
function="Button.SetFloaterToggle"
parameter="phototools"/>
</button>
</panel>

View File

@ -2665,6 +2665,7 @@ Try enclosing path to the editor with double quotes.
<string name="Command_MiniMap_Label">Mini-map</string>
<string name="Command_Move_Label">Walk / run / fly</string>
<string name="Command_People_Label">People</string>
<string name="Command_Performance_Label">Graphics speed</string>
<string name="Command_Picks_Label">Picks</string>
<string name="Command_Places_Label">Places</string>
<string name="Command_Preferences_Label">Preferences</string>
@ -2730,6 +2731,7 @@ Try enclosing path to the editor with double quotes.
<string name="Command_MiniMap_Tooltip">Show nearby people (CTRL+SHIFT+M)</string>
<string name="Command_Move_Tooltip">Moving your avatar</string>
<string name="Command_People_Tooltip">Friends, groups, and nearby people (CTRL+SHIFT+A)</string>
<string name="Command_Performance_Tooltip">Tune graphics settings</string>
<string name="Command_Picks_Tooltip">Places to show as favorites in your profile</string>
<string name="Command_Places_Tooltip">Places you've saved (ALT+H)</string>
<string name="Command_Preferences_Tooltip">Preferences (CTRL+P)</string>
@ -2928,7 +2930,7 @@ Try enclosing path to the editor with double quotes.
<string name="preset_combo_label">-Empty list-</string>
<string name="Default">Default</string>
<string name="none_paren_cap">(None)</string>
<string name="no_limit">No Limit</string>
<string name="no_limit">No limit</string>
<string name="Mav_Details_MAV_FOUND_DEGENERATE_TRIANGLES">
The physics shape contains triangles which are too small. Try simplifying the physics model.

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<floater name="floater_avatar_render_settings" title="Ustawienia renderowania awatarów">
<floater name="floater_avatar_render_settings" title="Wyjątki renderowania awatarów">
<string name="av_never_render" value="Nigdy"/>
<string name="av_always_render" value="Zawsze"/>
<filter_editor label="Filtruj ludzi" name="people_filter_input" />
<menu_button name="plus_btn" tool_tip="Akcje dotyczące wybranej osoby" />
<name_list name="render_settings_list">
<name_list.columns label="Imię" name="name" />
<name_list.columns label="Renderowanie" name="setting" />
<name_list.columns label="Dodano" name="timestamp" />
<name_list.columns label="Pełne detale" name="setting" />
</name_list>
<panel name="add_subpanel">
<menu_button label="Dodaj kogoś..." name="plus_btn" tool_tip="Działania na wybranej osobie" />
</panel>
</floater>

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