forked from blender/blender
main sync #3
@ -161,25 +161,12 @@ ShaderCache::~ShaderCache()
|
|||||||
running = false;
|
running = false;
|
||||||
cond_var.notify_all();
|
cond_var.notify_all();
|
||||||
|
|
||||||
int num_incomplete = int(incomplete_requests);
|
metal_printf("Waiting for ShaderCache threads... (incomplete_requests = %d)\n",
|
||||||
if (num_incomplete) {
|
int(incomplete_requests));
|
||||||
/* Shutting down the app with incomplete shader compilation requests. Give 1 second's grace for
|
|
||||||
* clean shutdown. */
|
|
||||||
metal_printf("ShaderCache busy (incomplete_requests = %d)...\n", num_incomplete);
|
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
|
||||||
num_incomplete = int(incomplete_requests);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num_incomplete && !MetalDeviceKernels::is_benchmark_warmup()) {
|
|
||||||
metal_printf("ShaderCache still busy (incomplete_requests = %d). Terminating...\n",
|
|
||||||
num_incomplete);
|
|
||||||
std::terminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
metal_printf("ShaderCache idle. Shutting down.\n");
|
|
||||||
for (auto &thread : compile_threads) {
|
for (auto &thread : compile_threads) {
|
||||||
thread.join();
|
thread.join();
|
||||||
}
|
}
|
||||||
|
metal_printf("ShaderCache shut down.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderCache::wait_for_all()
|
void ShaderCache::wait_for_all()
|
||||||
@ -675,7 +662,9 @@ void MetalKernelPipeline::compile()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__block bool creating_new_archive = false;
|
bool creating_new_archive = false;
|
||||||
|
bool recreate_archive = false;
|
||||||
|
|
||||||
if (@available(macOS 11.0, *)) {
|
if (@available(macOS 11.0, *)) {
|
||||||
if (use_binary_archive) {
|
if (use_binary_archive) {
|
||||||
if (!archive) {
|
if (!archive) {
|
||||||
@ -684,51 +673,101 @@ void MetalKernelPipeline::compile()
|
|||||||
archive = [mtlDevice newBinaryArchiveWithDescriptor:archiveDesc error:nil];
|
archive = [mtlDevice newBinaryArchiveWithDescriptor:archiveDesc error:nil];
|
||||||
creating_new_archive = true;
|
creating_new_archive = true;
|
||||||
}
|
}
|
||||||
computePipelineStateDescriptor.binaryArchives = [NSArray arrayWithObjects:archive, nil];
|
else {
|
||||||
pipelineOptions = MTLPipelineOptionFailOnBinaryArchiveMiss;
|
pipelineOptions = MTLPipelineOptionFailOnBinaryArchiveMiss;
|
||||||
|
computePipelineStateDescriptor.binaryArchives = [NSArray arrayWithObjects:archive, nil];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double starttime = time_dt();
|
/* Lambda to do the actual pipeline compilation. */
|
||||||
|
auto do_compilation = [&]() {
|
||||||
|
__block bool compilation_finished = false;
|
||||||
|
__block string error_str;
|
||||||
|
|
||||||
/* Block on load to ensure we continue with a valid kernel function */
|
if (archive && path_exists(metalbin_path)) {
|
||||||
if (creating_new_archive) {
|
/* Use the blocking variant of newComputePipelineStateWithDescriptor if an archive exists on
|
||||||
starttime = time_dt();
|
* disk. It should load almost instantaneously, and will fail gracefully when loading a
|
||||||
|
* corrupt archive (unlike the async variant). */
|
||||||
|
NSError *error = nil;
|
||||||
|
pipeline = [mtlDevice newComputePipelineStateWithDescriptor:computePipelineStateDescriptor
|
||||||
|
options:pipelineOptions
|
||||||
|
reflection:nullptr
|
||||||
|
error:&error];
|
||||||
|
const char *err = error ? [[error localizedDescription] UTF8String] : nullptr;
|
||||||
|
error_str = err ? err : "nil";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Use the async variant of newComputePipelineStateWithDescriptor if no archive exists on
|
||||||
|
* disk. This allows us responds to app shutdown. */
|
||||||
|
[mtlDevice
|
||||||
|
newComputePipelineStateWithDescriptor:computePipelineStateDescriptor
|
||||||
|
options:pipelineOptions
|
||||||
|
completionHandler:^(id<MTLComputePipelineState> computePipelineState,
|
||||||
|
MTLComputePipelineReflection *reflection,
|
||||||
|
NSError *error) {
|
||||||
|
pipeline = computePipelineState;
|
||||||
|
|
||||||
|
/* Retain the pipeline so we can use it safely past the completion
|
||||||
|
* handler. */
|
||||||
|
if (pipeline) {
|
||||||
|
[pipeline retain];
|
||||||
|
}
|
||||||
|
const char *err = error ?
|
||||||
|
[[error localizedDescription] UTF8String] :
|
||||||
|
nullptr;
|
||||||
|
error_str = err ? err : "nil";
|
||||||
|
|
||||||
|
compilation_finished = true;
|
||||||
|
}];
|
||||||
|
|
||||||
|
/* Immediately wait for either the compilation to finish or for app shutdown. */
|
||||||
|
while (ShaderCache::running && !compilation_finished) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (creating_new_archive && pipeline && ShaderCache::running) {
|
||||||
|
/* Add pipeline into the new archive. It should be instantaneous following
|
||||||
|
* newComputePipelineStateWithDescriptor. */
|
||||||
NSError *error;
|
NSError *error;
|
||||||
|
|
||||||
|
computePipelineStateDescriptor.binaryArchives = [NSArray arrayWithObjects:archive, nil];
|
||||||
if (![archive addComputePipelineFunctionsWithDescriptor:computePipelineStateDescriptor
|
if (![archive addComputePipelineFunctionsWithDescriptor:computePipelineStateDescriptor
|
||||||
error:&error]) {
|
error:&error]) {
|
||||||
NSString *errStr = [error localizedDescription];
|
NSString *errStr = [error localizedDescription];
|
||||||
metal_printf("Failed to add PSO to archive:\n%s\n", errStr ? [errStr UTF8String] : "nil");
|
metal_printf("Failed to add PSO to archive:\n%s\n", errStr ? [errStr UTF8String] : "nil");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!pipeline) {
|
||||||
pipeline = [mtlDevice newComputePipelineStateWithDescriptor:computePipelineStateDescriptor
|
|
||||||
options:pipelineOptions
|
|
||||||
reflection:nullptr
|
|
||||||
error:&error];
|
|
||||||
|
|
||||||
bool recreate_archive = false;
|
|
||||||
if (pipeline == nil && archive) {
|
|
||||||
NSString *errStr = [error localizedDescription];
|
|
||||||
metal_printf(
|
metal_printf(
|
||||||
"Failed to create compute pipeline state \"%s\" from archive - attempting recreation... "
|
"newComputePipelineStateWithDescriptor failed for \"%s\"%s. "
|
||||||
"(error: %s)\n",
|
"Error:\n%s\n",
|
||||||
device_kernel_as_string((DeviceKernel)device_kernel),
|
device_kernel_as_string((DeviceKernel)device_kernel),
|
||||||
errStr ? [errStr UTF8String] : "nil");
|
(archive && !recreate_archive) ? " Archive may be incomplete or corrupt - attempting "
|
||||||
pipeline = [mtlDevice newComputePipelineStateWithDescriptor:computePipelineStateDescriptor
|
"recreation.." :
|
||||||
options:MTLPipelineOptionNone
|
"",
|
||||||
reflection:nullptr
|
error_str.c_str());
|
||||||
error:&error];
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
double starttime = time_dt();
|
||||||
|
|
||||||
|
do_compilation();
|
||||||
|
|
||||||
|
/* An archive might have a corrupt entry and fail to materialize the pipeline. This shouldn't
|
||||||
|
* happen, but if it does we recreate it. */
|
||||||
|
if (pipeline == nil && archive) {
|
||||||
recreate_archive = true;
|
recreate_archive = true;
|
||||||
|
pipelineOptions = MTLPipelineOptionNone;
|
||||||
|
path_remove(metalbin_path);
|
||||||
|
|
||||||
|
do_compilation();
|
||||||
}
|
}
|
||||||
|
|
||||||
double duration = time_dt() - starttime;
|
double duration = time_dt() - starttime;
|
||||||
|
|
||||||
if (pipeline == nil) {
|
if (pipeline == nil) {
|
||||||
NSString *errStr = [error localizedDescription];
|
|
||||||
error_str = string_printf("Failed to create compute pipeline state \"%s\", error: \n",
|
|
||||||
device_kernel_as_string((DeviceKernel)device_kernel));
|
|
||||||
error_str += (errStr ? [errStr UTF8String] : "nil");
|
|
||||||
metal_printf("%16s | %2d | %-55s | %7.2fs | FAILED!\n",
|
metal_printf("%16s | %2d | %-55s | %7.2fs | FAILED!\n",
|
||||||
kernel_type_as_string(pso_type),
|
kernel_type_as_string(pso_type),
|
||||||
device_kernel,
|
device_kernel,
|
||||||
@ -748,7 +787,8 @@ void MetalKernelPipeline::compile()
|
|||||||
if (creating_new_archive || recreate_archive) {
|
if (creating_new_archive || recreate_archive) {
|
||||||
if (![archive serializeToURL:[NSURL fileURLWithPath:@(metalbin_path.c_str())]
|
if (![archive serializeToURL:[NSURL fileURLWithPath:@(metalbin_path.c_str())]
|
||||||
error:&error]) {
|
error:&error]) {
|
||||||
metal_printf("Failed to save binary archive, error:\n%s\n",
|
metal_printf("Failed to save binary archive to %s, error:\n%s\n",
|
||||||
|
metalbin_path.c_str(),
|
||||||
[[error localizedDescription] UTF8String]);
|
[[error localizedDescription] UTF8String]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#ifndef __FFMPEG_COMPAT_H__
|
#ifndef __FFMPEG_COMPAT_H__
|
||||||
#define __FFMPEG_COMPAT_H__
|
#define __FFMPEG_COMPAT_H__
|
||||||
|
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
#include <libavformat/avformat.h>
|
#include <libavformat/avformat.h>
|
||||||
|
|
||||||
/* Check if our ffmpeg is new enough, avoids user complaints.
|
/* Check if our ffmpeg is new enough, avoids user complaints.
|
||||||
|
@ -5912,7 +5912,8 @@ static bool ui_layout_has_panel_label(const uiLayout *layout, const PanelType *p
|
|||||||
LISTBASE_FOREACH (uiItem *, subitem, &layout->items) {
|
LISTBASE_FOREACH (uiItem *, subitem, &layout->items) {
|
||||||
if (subitem->type == ITEM_BUTTON) {
|
if (subitem->type == ITEM_BUTTON) {
|
||||||
uiButtonItem *bitem = (uiButtonItem *)subitem;
|
uiButtonItem *bitem = (uiButtonItem *)subitem;
|
||||||
if (!(bitem->but->flag & UI_HIDDEN) && STREQ(bitem->but->str, pt->label)) {
|
if (!(bitem->but->flag & UI_HIDDEN) &&
|
||||||
|
STREQ(bitem->but->str, CTX_IFACE_(pt->translation_context, pt->label))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,11 +62,24 @@ template<> uint denormalize<uint>(float val)
|
|||||||
return uint(float(DEPTH_SCALE_FACTOR) * val);
|
return uint(float(DEPTH_SCALE_FACTOR) * val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Float to other type case. */
|
||||||
template<typename T> T convert_type(float type)
|
template<typename T> T convert_type(float type)
|
||||||
{
|
{
|
||||||
return T(type);
|
return T(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Uint to other types. */
|
||||||
|
template<typename T> T convert_type(uint type)
|
||||||
|
{
|
||||||
|
return T(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Int to other types. */
|
||||||
|
template<typename T> T convert_type(int type)
|
||||||
|
{
|
||||||
|
return T(type);
|
||||||
|
}
|
||||||
|
|
||||||
template<> uchar convert_type<uchar>(float val)
|
template<> uchar convert_type<uchar>(float val)
|
||||||
{
|
{
|
||||||
return uchar(val * float(0xFF));
|
return uchar(val * float(0xFF));
|
||||||
@ -141,8 +154,8 @@ kernel void compute_texture_read(constant TextureReadParams ¶ms [[buffer(0)]
|
|||||||
uint xx = position[0];
|
uint xx = position[0];
|
||||||
uint yy = position[1];
|
uint yy = position[1];
|
||||||
uint zz = position[2];
|
uint zz = position[2];
|
||||||
int index = (zz * (params.extent[0] * params.extent[1]) + yy * params.extnt[0] + xx) *
|
int index = (zz * (params.extent[0] * params.extent[1]) + yy * params.extent[0] + xx) *
|
||||||
COMPONENT_COUNT_INPUT;
|
COMPONENT_COUNT_OUTPUT;
|
||||||
read_colour = read_tex.read(uint3(params.offset[0], params.offset[1], params.offset[2]) +
|
read_colour = read_tex.read(uint3(params.offset[0], params.offset[1], params.offset[2]) +
|
||||||
uint3(xx, yy, zz));
|
uint3(xx, yy, zz));
|
||||||
|
|
||||||
@ -163,7 +176,7 @@ kernel void compute_texture_read(constant TextureReadParams ¶ms [[buffer(0)]
|
|||||||
uint yy = position[1];
|
uint yy = position[1];
|
||||||
uint layer = position[2];
|
uint layer = position[2];
|
||||||
int index = (layer * (params.extent[0] * params.extent[1]) + yy * params.extent[0] + xx) *
|
int index = (layer * (params.extent[0] * params.extent[1]) + yy * params.extent[0] + xx) *
|
||||||
COMPONENT_COUNT_INPUT;
|
COMPONENT_COUNT_OUTPUT;
|
||||||
|
|
||||||
/* Read data */
|
/* Read data */
|
||||||
# if IS_DEPTH_FORMAT == 1
|
# if IS_DEPTH_FORMAT == 1
|
||||||
|
@ -606,17 +606,6 @@ void MTLFrameBuffer::update_attachments(bool update_viewport)
|
|||||||
if (!dirty_attachments_) {
|
if (!dirty_attachments_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cache viewport and scissor (If we have existing attachments). */
|
|
||||||
int t_viewport[4], t_scissor[4];
|
|
||||||
update_viewport = update_viewport &&
|
|
||||||
(this->get_attachment_count() > 0 && this->has_depth_attachment() &&
|
|
||||||
this->has_stencil_attachment());
|
|
||||||
if (update_viewport) {
|
|
||||||
this->viewport_get(t_viewport);
|
|
||||||
this->scissor_get(t_scissor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear current attachments state. */
|
/* Clear current attachments state. */
|
||||||
this->remove_all_attachments();
|
this->remove_all_attachments();
|
||||||
|
|
||||||
@ -738,21 +727,24 @@ void MTLFrameBuffer::update_attachments(bool update_viewport)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check whether the first attachment is SRGB. */
|
/* Extract attachment size and determine if framebuffer is SRGB. */
|
||||||
if (first_attachment != GPU_FB_MAX_ATTACHMENT) {
|
if (first_attachment != GPU_FB_MAX_ATTACHMENT) {
|
||||||
srgb_ = (first_attachment_mtl.texture->format_get() == GPU_SRGB8_A8);
|
/* Ensure size is correctly assigned. */
|
||||||
}
|
GPUAttachment &attach = attachments_[first_attachment];
|
||||||
|
int size[3];
|
||||||
/* Reset viewport and Scissor (If viewport is smaller or equal to the framebuffer size). */
|
GPU_texture_get_mipmap_size(attach.tex, attach.mip, size);
|
||||||
if (update_viewport && t_viewport[2] <= width_ && t_viewport[3] <= height_) {
|
this->size_set(size[0], size[1]);
|
||||||
|
srgb_ = (GPU_texture_format(attach.tex) == GPU_SRGB8_A8);
|
||||||
this->viewport_set(t_viewport);
|
|
||||||
this->scissor_set(t_viewport);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
/* Empty frame-buffer. */
|
||||||
|
width_ = 0;
|
||||||
|
height_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset viewport and Scissor. */
|
||||||
this->viewport_reset();
|
this->viewport_reset();
|
||||||
this->scissor_reset();
|
this->scissor_reset();
|
||||||
}
|
|
||||||
|
|
||||||
/* We have now updated our internal structures. */
|
/* We have now updated our internal structures. */
|
||||||
dirty_attachments_ = false;
|
dirty_attachments_ = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user