Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/core/threading_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,14 @@ class PosixConditionBase {
? std::chrono::steady_clock::time_point::max()
: start_time + timeout;

// The poll interval backs off exponentially (capped) the longer nothing
// is signaled, so a long idle wait doesn't keep re-locking every handle's
// mutex ~1000 times/sec (measured as a real CPU cost on waits across
// several handles, e.g. AudioSystem's per-client semaphore WaitAny).
// Freshly started/likely-to-resolve-soon waits still poll at 1ms.
auto poll_interval = std::chrono::milliseconds(1);
constexpr auto kMaxPollInterval = std::chrono::milliseconds(16);

while (true) {
size_t first_signaled = std::numeric_limits<size_t>::max();
bool condition_met = false;
Expand Down Expand Up @@ -358,12 +366,13 @@ class PosixConditionBase {
}

if (timeout == std::chrono::milliseconds::max()) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
std::this_thread::sleep_for(poll_interval);
} else {
auto remaining = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - now);
auto sleep_time = std::min(remaining, std::chrono::milliseconds(1));
auto sleep_time = std::min(remaining, poll_interval);
std::this_thread::sleep_for(sleep_time);
}
poll_interval = std::min(poll_interval * 2, kMaxPollInterval);
}
}

Expand Down
19 changes: 15 additions & 4 deletions src/graphics/pipeline/shader/spirv_translator_fetch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1409,8 +1409,7 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
builder_->createUnaryOp(spv::OpLogicalNot, type_bool_, is_all_signed);

// Load the fetch constant word 4, needed unconditionally for LOD
// biasing, for result exponent biasing, and conditionally for stacked
// texture filtering.
// biasing and conditionally for stacked texture filtering.
id_vector_temp_.clear();
id_vector_temp_.push_back(const_int_0_);
id_vector_temp_.push_back(
Expand Down Expand Up @@ -2030,10 +2029,22 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
}

// Apply the exponent bias from the bits 13:18 of the fetch constant
// word 4.
// word 3.
id_vector_temp_.clear();
id_vector_temp_.push_back(const_int_0_);
id_vector_temp_.push_back(
builder_->makeIntConstant(int((fetch_constant_word_0_index + 3) >> 2)));
id_vector_temp_.push_back(
builder_->makeIntConstant(int((fetch_constant_word_0_index + 3) & 3)));
spv::Id fetch_constant_word_3 = builder_->createLoad(
builder_->createAccessChain(spv::StorageClassUniform, uniform_fetch_constants_,
id_vector_temp_),
spv::NoPrecision);
spv::Id fetch_constant_word_3_signed =
builder_->createUnaryOp(spv::OpBitcast, type_int_, fetch_constant_word_3);
spv::Id result_exponent_bias = builder_->createBinBuiltinCall(
type_float_, ext_inst_glsl_std_450_, GLSLstd450Ldexp, const_float_1_,
builder_->createTriOp(spv::OpBitFieldSExtract, type_int_, fetch_constant_word_4_signed,
builder_->createTriOp(spv::OpBitFieldSExtract, type_int_, fetch_constant_word_3_signed,
builder_->makeUintConstant(13), builder_->makeUintConstant(6)));
{
uint32_t result_remaining_components = used_result_nonzero_components;
Expand Down
42 changes: 28 additions & 14 deletions src/graphics/vulkan/pipeline_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1111,8 +1111,8 @@ bool VulkanPipelineCache::ConfigurePipeline(
}
}

bool use_async = REXCVAR_GET(async_shader_compilation) && !creation_threads_.empty() &&
pixel_shader && placeholder_pixel_shader_ != VK_NULL_HANDLE;
bool use_async = REXCVAR_GET(async_shader_compilation) && !creation_threads_.empty();
bool use_placeholder_swap = use_async && pixel_shader && placeholder_pixel_shader_ != VK_NULL_HANDLE;
uint8_t async_priority = pipeline_util::kPriorityLowest;
if (use_async) {
uint32_t bound_rts =
Expand Down Expand Up @@ -1159,20 +1159,34 @@ bool VulkanPipelineCache::ConfigurePipeline(
bool queued_async_creation = false;
if (use_async) {
creation_arguments_real.priority = async_priority;
PipelineCreationArguments creation_arguments_placeholder;
if (TryGetPipelineCreationArgumentsForDescription(description, &pipeline,
creation_arguments_placeholder, true)) {
pipeline.second.is_placeholder.store(true, std::memory_order_release);
if (EnsurePipelineCreated(creation_arguments_placeholder, placeholder_pixel_shader_)) {
{
std::lock_guard<std::mutex> lock(creation_request_lock_);
creation_queue_.push(creation_arguments_real);
if (use_placeholder_swap) {
PipelineCreationArguments creation_arguments_placeholder;
if (TryGetPipelineCreationArgumentsForDescription(description, &pipeline,
creation_arguments_placeholder, true)) {
pipeline.second.is_placeholder.store(true, std::memory_order_release);
if (EnsurePipelineCreated(creation_arguments_placeholder, placeholder_pixel_shader_)) {
{
std::lock_guard<std::mutex> lock(creation_request_lock_);
creation_queue_.push(creation_arguments_real);
}
creation_request_cond_.notify_one();
queued_async_creation = true;
} else {
pipeline.second.is_placeholder.store(false, std::memory_order_release);
}
creation_request_cond_.notify_one();
queued_async_creation = true;
} else {
pipeline.second.is_placeholder.store(false, std::memory_order_release);
}
} else {
// No pixel shader (e.g. depth/shadow-only pipelines): there is nothing
// cheaper to substitute while the real pipeline compiles on a
// background thread, so skip drawing with it for a few frames instead
// of blocking the render thread on synchronous compilation.
pipeline.second.is_placeholder.store(true, std::memory_order_release);
{
std::lock_guard<std::mutex> lock(creation_request_lock_);
creation_queue_.push(creation_arguments_real);
}
creation_request_cond_.notify_one();
queued_async_creation = true;
}
}

Expand Down
Loading