Merge "libvulkan: Support R5G6B5_UNORM_PACK16 as a swapchain format" into nyc-dev
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index 8515a01..a4b5ff1 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -18,7 +18,7 @@
# ZipArchive support, the order matters here to get all symbols.
LOCAL_STATIC_LIBRARIES := libziparchive libz libbase libmincrypt
LOCAL_HAL_STATIC_LIBRARIES := libdumpstate
-LOCAL_CFLAGS += -Wall -Wno-unused-parameter -std=gnu99
+LOCAL_CFLAGS += -Wall -Werror -Wno-unused-parameter -std=gnu99
LOCAL_INIT_RC := dumpstate.rc
include $(BUILD_EXECUTABLE)
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 98617f4..6520e3b 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -144,7 +144,7 @@
mount_points.clear();
DurationReporter duration_reporter(title, NULL);
for_each_pid(do_mountinfo, NULL);
- MYLOGD("%s: %lu entries added to zip file\n", title, mount_points.size());
+ MYLOGD("%s: %d entries added to zip file\n", title, (int) mount_points.size());
}
static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
@@ -613,6 +613,7 @@
run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
+ for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
if (!screenshot_path.empty()) {
MYLOGI("taking late screenshot\n");
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 5a93f8c..a8aea42 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -30,15 +30,15 @@
#endif
#ifndef MYLOGD
-#define MYLOGD(fmt...) fprintf(stderr, fmt); ALOGD(fmt);
+#define MYLOGD(...) fprintf(stderr, __VA_ARGS__); ALOGD(__VA_ARGS__);
#endif
#ifndef MYLOGI
-#define MYLOGI(fmt...) fprintf(stderr, fmt); ALOGI(fmt);
+#define MYLOGI(...) fprintf(stderr, __VA_ARGS__); ALOGI(__VA_ARGS__);
#endif
#ifndef MYLOGE
-#define MYLOGE(fmt...) fprintf(stderr, fmt); ALOGE(fmt);
+#define MYLOGE(...) fprintf(stderr, __VA_ARGS__); ALOGE(__VA_ARGS__);
#endif
#include <time.h>
@@ -138,6 +138,9 @@
/* Displays a blocked processes in-kernel wait channel */
void show_wchan(int pid, int tid, const char *name);
+/* Displays a processes times */
+void show_showtime(int pid, const char *name);
+
/* Runs "showmap" for a process */
void do_showmap(int pid, const char *name);
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 683091f..6dfd7a8 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -27,6 +27,7 @@
#include <string.h>
#include <sys/inotify.h>
#include <sys/stat.h>
+#include <sys/sysconf.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/klog.h>
@@ -133,13 +134,32 @@
continue;
}
- sprintf(cmdpath,"/proc/%d/cmdline", pid);
memset(cmdline, 0, sizeof(cmdline));
- if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) < 0) {
- strcpy(cmdline, "N/A");
- } else {
- read(fd, cmdline, sizeof(cmdline) - 1);
+
+ snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
+ if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
+ TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
close(fd);
+ if (cmdline[0]) {
+ helper(pid, cmdline, arg);
+ continue;
+ }
+ }
+
+ // if no cmdline, a kernel thread has comm
+ snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
+ if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
+ TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
+ close(fd);
+ if (cmdline[1]) {
+ cmdline[0] = '[';
+ size_t len = strcspn(cmdline, "\f\b\r\n");
+ cmdline[len] = ']';
+ cmdline[len+1] = '\0';
+ }
+ }
+ if (!cmdline[0]) {
+ strcpy(cmdline, "N/A");
}
helper(pid, cmdline, arg);
}
@@ -191,7 +211,7 @@
strcpy(comm, "N/A");
} else {
char *c;
- read(fd, comm, sizeof(comm) - 1);
+ TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
close(fd);
c = strrchr(comm, '\n');
@@ -214,7 +234,7 @@
ON_DRY_RUN_RETURN();
char path[255];
char buffer[255];
- int fd;
+ int fd, ret, save_errno;
char name_buffer[255];
memset(buffer, 0, sizeof(buffer));
@@ -225,9 +245,13 @@
return;
}
- if (read(fd, buffer, sizeof(buffer)) < 0) {
- printf("Failed to read '%s' (%s)\n", path, strerror(errno));
- goto out_close;
+ ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+ save_errno = errno;
+ close(fd);
+
+ if (ret < 0) {
+ printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
+ return;
}
snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
@@ -235,8 +259,103 @@
printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
-out_close:
+ return;
+}
+
+// print time in centiseconds
+static void snprcent(char *buffer, size_t len, size_t spc,
+ unsigned long long time) {
+ static long hz; // cache discovered hz
+
+ if (hz <= 0) {
+ hz = sysconf(_SC_CLK_TCK);
+ if (hz <= 0) {
+ hz = 1000;
+ }
+ }
+
+ // convert to centiseconds
+ time = (time * 100 + (hz / 2)) / hz;
+
+ char str[16];
+
+ snprintf(str, sizeof(str), " %llu.%02u",
+ time / 100, (unsigned)(time % 100));
+ size_t offset = strlen(buffer);
+ snprintf(buffer + offset, (len > offset) ? len - offset : 0,
+ "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
+}
+
+// print permille as a percent
+static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
+ char str[16];
+
+ snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
+ size_t offset = strlen(buffer);
+ snprintf(buffer + offset, (len > offset) ? len - offset : 0,
+ "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
+}
+
+void show_showtime(int pid, const char *name) {
+ ON_DRY_RUN_RETURN();
+ char path[255];
+ char buffer[1023];
+ int fd, ret, save_errno;
+
+ memset(buffer, 0, sizeof(buffer));
+
+ sprintf(path, "/proc/%d/stat", pid);
+ if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
+ printf("Failed to open '%s' (%s)\n", path, strerror(errno));
+ return;
+ }
+
+ ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+ save_errno = errno;
close(fd);
+
+ if (ret < 0) {
+ printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
+ return;
+ }
+
+ // field 14 is utime
+ // field 15 is stime
+ // field 42 is iotime
+ unsigned long long utime = 0, stime = 0, iotime = 0;
+ if (sscanf(buffer,
+ "%*llu %*s %*s %*lld %*lld %*lld %*lld %*lld %*lld %*lld %*lld "
+ "%*lld %*lld %llu %llu %*lld %*lld %*lld %*lld %*lld %*lld "
+ "%*lld %*lld %*lld %*lld %*lld %*lld %*lld %*lld %*lld %*lld "
+ "%*lld %*lld %*lld %*lld %*lld %*lld %*lld %*lld %*lld %llu ",
+ &utime, &stime, &iotime) != 3) {
+ return;
+ }
+
+ unsigned long long total = utime + stime;
+ if (!total) {
+ return;
+ }
+
+ unsigned permille = (iotime * 1000 + (total / 2)) / total;
+ if (permille > 1000) {
+ permille = 1000;
+ }
+
+ // try to beautify and stabilize columns at <80 characters
+ snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
+ if ((name[0] != '[') || utime) {
+ snprcent(buffer, sizeof(buffer), 57, utime);
+ }
+ snprcent(buffer, sizeof(buffer), 65, stime);
+ if ((name[0] != '[') || iotime) {
+ snprcent(buffer, sizeof(buffer), 73, iotime);
+ }
+ if (iotime) {
+ snprdec(buffer, sizeof(buffer), 79, permille);
+ }
+ puts(buffer); // adds a trailing newline
+
return;
}
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 8e2cf58..f8de675 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -238,18 +238,20 @@
return VK_ERROR_INITIALIZATION_FAILED;
}
- capabilities->currentExtent =
- VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)};
-
// TODO(jessehall): Figure out what the min/max values should be.
capabilities->minImageCount = 2;
capabilities->maxImageCount = 3;
+ capabilities->currentExtent =
+ VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)};
+
// TODO(jessehall): Figure out what the max extent should be. Maximum
// texture dimension maybe?
capabilities->minImageExtent = VkExtent2D{1, 1};
capabilities->maxImageExtent = VkExtent2D{4096, 4096};
+ capabilities->maxImageArrayLayers = 1;
+
// TODO(jessehall): We can support all transforms, fix this once
// implemented.
capabilities->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
@@ -257,7 +259,9 @@
// TODO(jessehall): Implement based on NATIVE_WINDOW_TRANSFORM_HINT.
capabilities->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
- capabilities->maxImageArrayLayers = 1;
+ // On Android, window composition is a WindowManager property, not something
+ // associated with the bufferqueue. It can't be changed from here.
+ capabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
// TODO(jessehall): I think these are right, but haven't thought hard about
// it. Do we need to query the driver for support of any of these?
@@ -345,8 +349,10 @@
"swapchain re-creation not yet implemented");
ALOGE_IF(create_info->preTransform != VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
"swapchain preTransform not yet implemented");
- ALOGE_IF(create_info->presentMode != VK_PRESENT_MODE_FIFO_KHR,
- "present modes other than FIFO are not yet implemented");
+ ALOGW_IF(!(create_info->presentMode == VK_PRESENT_MODE_FIFO_KHR ||
+ create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR),
+ "swapchain present mode %d not supported",
+ create_info->presentMode);
// -- Configure the native window --
@@ -416,6 +422,13 @@
ALOGE("window->query failed: %s (%d)", strerror(-err), err);
return VK_ERROR_INITIALIZATION_FAILED;
}
+ // The MIN_UNDEQUEUED_BUFFERS query doesn't know whether we'll be using
+ // async mode or not, and assumes not. But in async mode, the BufferQueue
+ // requires an extra undequeued buffer.
+ // See BufferQueueCore::getMinUndequeuedBufferCountLocked().
+ if (create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR)
+ min_undequeued_buffers += 1;
+
uint32_t num_images =
(create_info->minImageCount - 1) + min_undequeued_buffers;
err = native_window_set_buffer_count(surface.window.get(), num_images);
@@ -448,6 +461,17 @@
return VK_ERROR_INITIALIZATION_FAILED;
}
+ err = surface.window->setSwapInterval(
+ surface.window.get(),
+ create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1);
+ if (err != 0) {
+ // TODO(jessehall): Improve error reporting. Can we enumerate possible
+ // errors and translate them to valid Vulkan result codes?
+ ALOGE("native_window->setSwapInterval failed: %s (%d)", strerror(-err),
+ err);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
// -- Allocate our Swapchain object --
// After this point, we must deallocate the swapchain on error.
diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp
index 8f47bd1..cd61e86 100644
--- a/vulkan/nulldrv/null_driver.cpp
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -89,7 +89,7 @@
};
} // namespace HandleType
-const VkDeviceSize kMaxDeviceMemory = VkDeviceSize(INTPTR_MAX) + 1;
+const VkDeviceSize kMaxDeviceMemory = 0x10000000; // 256 MiB, arbitrary
} // anonymous namespace
@@ -346,6 +346,121 @@
strcpy(properties->deviceName, "Android Vulkan Null Driver");
memset(properties->pipelineCacheUUID, 0,
sizeof(properties->pipelineCacheUUID));
+ properties->limits = VkPhysicalDeviceLimits{
+ 4096, // maxImageDimension1D
+ 4096, // maxImageDimension2D
+ 256, // maxImageDimension3D
+ 4096, // maxImageDimensionCube
+ 256, // maxImageArrayLayers
+ 65536, // maxTexelBufferElements
+ 16384, // maxUniformBufferRange
+ 1 << 27, // maxStorageBufferRange
+ 128, // maxPushConstantsSize
+ 4096, // maxMemoryAllocationCount
+ 4000, // maxSamplerAllocationCount
+ 1, // bufferImageGranularity
+ 0, // sparseAddressSpaceSize
+ 4, // maxBoundDescriptorSets
+ 16, // maxPerStageDescriptorSamplers
+ 12, // maxPerStageDescriptorUniformBuffers
+ 4, // maxPerStageDescriptorStorageBuffers
+ 16, // maxPerStageDescriptorSampledImages
+ 4, // maxPerStageDescriptorStorageImages
+ 4, // maxPerStageDescriptorInputAttachments
+ 128, // maxPerStageResources
+ 96, // maxDescriptorSetSamplers
+ 72, // maxDescriptorSetUniformBuffers
+ 8, // maxDescriptorSetUniformBuffersDynamic
+ 24, // maxDescriptorSetStorageBuffers
+ 4, // maxDescriptorSetStorageBuffersDynamic
+ 96, // maxDescriptorSetSampledImages
+ 24, // maxDescriptorSetStorageImages
+ 4, // maxDescriptorSetInputAttachments
+ 16, // maxVertexInputAttributes
+ 16, // maxVertexInputBindings
+ 2047, // maxVertexInputAttributeOffset
+ 2048, // maxVertexInputBindingStride
+ 64, // maxVertexOutputComponents
+ 0, // maxTessellationGenerationLevel
+ 0, // maxTessellationPatchSize
+ 0, // maxTessellationControlPerVertexInputComponents
+ 0, // maxTessellationControlPerVertexOutputComponents
+ 0, // maxTessellationControlPerPatchOutputComponents
+ 0, // maxTessellationControlTotalOutputComponents
+ 0, // maxTessellationEvaluationInputComponents
+ 0, // maxTessellationEvaluationOutputComponents
+ 0, // maxGeometryShaderInvocations
+ 0, // maxGeometryInputComponents
+ 0, // maxGeometryOutputComponents
+ 0, // maxGeometryOutputVertices
+ 0, // maxGeometryTotalOutputComponents
+ 64, // maxFragmentInputComponents
+ 4, // maxFragmentOutputAttachments
+ 0, // maxFragmentDualSrcAttachments
+ 4, // maxFragmentCombinedOutputResources
+ 16384, // maxComputeSharedMemorySize
+ {65536, 65536, 65536}, // maxComputeWorkGroupCount[3]
+ 128, // maxComputeWorkGroupInvocations
+ {128, 128, 64}, // maxComputeWorkGroupSize[3]
+ 4, // subPixelPrecisionBits
+ 4, // subTexelPrecisionBits
+ 4, // mipmapPrecisionBits
+ UINT32_MAX, // maxDrawIndexedIndexValue
+ 1, // maxDrawIndirectCount
+ 2, // maxSamplerLodBias
+ 1, // maxSamplerAnisotropy
+ 1, // maxViewports
+ {4096, 4096}, // maxViewportDimensions[2]
+ {-8192.0f, 8191.0f}, // viewportBoundsRange[2]
+ 0, // viewportSubPixelBits
+ 64, // minMemoryMapAlignment
+ 256, // minTexelBufferOffsetAlignment
+ 256, // minUniformBufferOffsetAlignment
+ 256, // minStorageBufferOffsetAlignment
+ -8, // minTexelOffset
+ 7, // maxTexelOffset
+ 0, // minTexelGatherOffset
+ 0, // maxTexelGatherOffset
+ 0.0f, // minInterpolationOffset
+ 0.0f, // maxInterpolationOffset
+ 0, // subPixelInterpolationOffsetBits
+ 4096, // maxFramebufferWidth
+ 4096, // maxFramebufferHeight
+ 256, // maxFramebufferLayers
+ VK_SAMPLE_COUNT_1_BIT |
+ VK_SAMPLE_COUNT_4_BIT, // framebufferColorSampleCounts
+ VK_SAMPLE_COUNT_1_BIT |
+ VK_SAMPLE_COUNT_4_BIT, // framebufferDepthSampleCounts
+ VK_SAMPLE_COUNT_1_BIT |
+ VK_SAMPLE_COUNT_4_BIT, // framebufferStencilSampleCounts
+ VK_SAMPLE_COUNT_1_BIT |
+ VK_SAMPLE_COUNT_4_BIT, // framebufferNoAttachmentsSampleCounts
+ 4, // maxColorAttachments
+ VK_SAMPLE_COUNT_1_BIT |
+ VK_SAMPLE_COUNT_4_BIT, // sampledImageColorSampleCounts
+ VK_SAMPLE_COUNT_1_BIT, // sampledImageIntegerSampleCounts
+ VK_SAMPLE_COUNT_1_BIT |
+ VK_SAMPLE_COUNT_4_BIT, // sampledImageDepthSampleCounts
+ VK_SAMPLE_COUNT_1_BIT |
+ VK_SAMPLE_COUNT_4_BIT, // sampledImageStencilSampleCounts
+ VK_SAMPLE_COUNT_1_BIT, // storageImageSampleCounts
+ 1, // maxSampleMaskWords
+ VK_TRUE, // timestampComputeAndGraphics
+ 1, // timestampPeriod
+ 0, // maxClipDistances
+ 0, // maxCullDistances
+ 0, // maxCombinedClipAndCullDistances
+ 2, // discreteQueuePriorities
+ {1.0f, 1.0f}, // pointSizeRange[2]
+ {1.0f, 1.0f}, // lineWidthRange[2]
+ 0.0f, // pointSizeGranularity
+ 0.0f, // lineWidthGranularity
+ VK_TRUE, // strictLines
+ VK_TRUE, // standardSampleLocations
+ 1, // optimalBufferCopyOffsetAlignment
+ 1, // optimalBufferCopyRowPitchAlignment
+ 64, // nonCoherentAtomSize
+ };
}
void GetPhysicalDeviceQueueFamilyProperties(
diff --git a/vulkan/tools/vkinfo.cpp b/vulkan/tools/vkinfo.cpp
index 462a8e5..9cbd234 100644
--- a/vulkan/tools/vkinfo.cpp
+++ b/vulkan/tools/vkinfo.cpp
@@ -342,7 +342,7 @@
strbuf << "DEVICE_LOCAL";
printf("%sHeap %u: %" PRIu64 " MiB (0x%" PRIx64 " B) %s\n",
Indent(indent + 1), heap,
- info.memory.memoryHeaps[heap].size / 0x1000000,
+ info.memory.memoryHeaps[heap].size / 0x100000,
info.memory.memoryHeaps[heap].size, strbuf.str().c_str());
strbuf.str(std::string());