Commit 52047de4 by Frank Henigman Committed by Commit Bot

Vulkan: support instanced draws. (reland)

Enable instanced draws with the Vulkan backend. So far it only works when Vulkan has VK_EXT_vertex_attribute_divisor. BUG=angleproject:2672 Change-Id: Ib6655625776344305911a1a742c85f17638cee8f Reviewed-on: https://chromium-review.googlesource.com/c/1469263Reviewed-by: 's avatarFrank Henigman <fjhenigman@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Frank Henigman <fjhenigman@chromium.org>
parent 0c01e367
...@@ -199,6 +199,7 @@ angle::Result ContextVk::setupDraw(const gl::Context *context, ...@@ -199,6 +199,7 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
GLint firstVertex, GLint firstVertex,
GLsizei vertexOrIndexCount, GLsizei vertexOrIndexCount,
GLsizei instanceCount,
gl::DrawElementsType indexTypeOrNone, gl::DrawElementsType indexTypeOrNone,
const void *indices, const void *indices,
DirtyBits dirtyBitMask, DirtyBits dirtyBitMask,
...@@ -216,7 +217,7 @@ angle::Result ContextVk::setupDraw(const gl::Context *context, ...@@ -216,7 +217,7 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
if (context->getStateCache().hasAnyActiveClientAttrib()) if (context->getStateCache().hasAnyActiveClientAttrib())
{ {
ANGLE_TRY(mVertexArray->updateClientAttribs(context, firstVertex, vertexOrIndexCount, ANGLE_TRY(mVertexArray->updateClientAttribs(context, firstVertex, vertexOrIndexCount,
indexTypeOrNone, indices)); instanceCount, indexTypeOrNone, indices));
mDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS); mDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
} }
...@@ -266,6 +267,7 @@ angle::Result ContextVk::setupDraw(const gl::Context *context, ...@@ -266,6 +267,7 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
angle::Result ContextVk::setupIndexedDraw(const gl::Context *context, angle::Result ContextVk::setupIndexedDraw(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
GLsizei indexCount, GLsizei indexCount,
GLsizei instanceCount,
gl::DrawElementsType indexType, gl::DrawElementsType indexType,
const void *indices, const void *indices,
vk::CommandBuffer **commandBufferOut) vk::CommandBuffer **commandBufferOut)
...@@ -297,8 +299,8 @@ angle::Result ContextVk::setupIndexedDraw(const gl::Context *context, ...@@ -297,8 +299,8 @@ angle::Result ContextVk::setupIndexedDraw(const gl::Context *context,
} }
} }
return setupDraw(context, mode, 0, indexCount, indexType, indices, mIndexedDirtyBitsMask, return setupDraw(context, mode, 0, indexCount, instanceCount, indexType, indices,
commandBufferOut); mIndexedDirtyBitsMask, commandBufferOut);
} }
angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context, angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
...@@ -315,7 +317,7 @@ angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context, ...@@ -315,7 +317,7 @@ angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
mCurrentDrawElementsType = indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum mCurrentDrawElementsType = indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum
? indexTypeOrInvalid ? indexTypeOrInvalid
: gl::DrawElementsType::UnsignedInt; : gl::DrawElementsType::UnsignedInt;
return setupDraw(context, mode, firstVertex, vertexOrIndexCount, indexTypeOrInvalid, indices, return setupDraw(context, mode, firstVertex, vertexOrIndexCount, 1, indexTypeOrInvalid, indices,
mIndexedDirtyBitsMask, commandBufferOut); mIndexedDirtyBitsMask, commandBufferOut);
} }
...@@ -455,8 +457,8 @@ angle::Result ContextVk::drawArrays(const gl::Context *context, ...@@ -455,8 +457,8 @@ angle::Result ContextVk::drawArrays(const gl::Context *context,
} }
else else
{ {
ANGLE_TRY(setupDraw(context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, ANGLE_TRY(setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum,
mNonIndexedDirtyBitsMask, &commandBuffer)); nullptr, mNonIndexedDirtyBitsMask, &commandBuffer));
commandBuffer->draw(clampedVertexCount, 1, first, 0); commandBuffer->draw(clampedVertexCount, 1, first, 0);
} }
...@@ -467,10 +469,20 @@ angle::Result ContextVk::drawArraysInstanced(const gl::Context *context, ...@@ -467,10 +469,20 @@ angle::Result ContextVk::drawArraysInstanced(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
GLint first, GLint first,
GLsizei count, GLsizei count,
GLsizei instanceCount) GLsizei instances)
{ {
if (mode == gl::PrimitiveMode::LineLoop)
{
// TODO - http://anglebug.com/2672
ANGLE_VK_UNREACHABLE(this); ANGLE_VK_UNREACHABLE(this);
return angle::Result::Stop; return angle::Result::Stop;
}
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
nullptr, mNonIndexedDirtyBitsMask, &commandBuffer));
commandBuffer->draw(gl::GetClampedVertexCount<uint32_t>(count), instances, first, 0);
return angle::Result::Continue;
} }
angle::Result ContextVk::drawElements(const gl::Context *context, angle::Result ContextVk::drawElements(const gl::Context *context,
...@@ -487,7 +499,7 @@ angle::Result ContextVk::drawElements(const gl::Context *context, ...@@ -487,7 +499,7 @@ angle::Result ContextVk::drawElements(const gl::Context *context,
} }
else else
{ {
ANGLE_TRY(setupIndexedDraw(context, mode, count, type, indices, &commandBuffer)); ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices, &commandBuffer));
commandBuffer->drawIndexed(count, 1, 0, 0, 0); commandBuffer->drawIndexed(count, 1, 0, 0, 0);
} }
...@@ -501,8 +513,17 @@ angle::Result ContextVk::drawElementsInstanced(const gl::Context *context, ...@@ -501,8 +513,17 @@ angle::Result ContextVk::drawElementsInstanced(const gl::Context *context,
const void *indices, const void *indices,
GLsizei instances) GLsizei instances)
{ {
if (mode == gl::PrimitiveMode::LineLoop)
{
// TODO - http://anglebug.com/2672
ANGLE_VK_UNREACHABLE(this); ANGLE_VK_UNREACHABLE(this);
return angle::Result::Stop; return angle::Result::Stop;
}
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices, &commandBuffer));
commandBuffer->drawIndexed(count, instances, 0, 0, 0);
return angle::Result::Continue;
} }
angle::Result ContextVk::drawRangeElements(const gl::Context *context, angle::Result ContextVk::drawRangeElements(const gl::Context *context,
......
...@@ -61,7 +61,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::CommandBuff ...@@ -61,7 +61,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::CommandBuff
GLsizei count, GLsizei count,
gl::DrawElementsType type, gl::DrawElementsType type,
const void *indices, const void *indices,
GLsizei instances) override; GLsizei instanceCount) override;
angle::Result drawRangeElements(const gl::Context *context, angle::Result drawRangeElements(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
GLuint start, GLuint start,
...@@ -232,6 +232,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::CommandBuff ...@@ -232,6 +232,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::CommandBuff
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
GLint firstVertex, GLint firstVertex,
GLsizei vertexOrIndexCount, GLsizei vertexOrIndexCount,
GLsizei instanceCount,
gl::DrawElementsType indexTypeOrInvalid, gl::DrawElementsType indexTypeOrInvalid,
const void *indices, const void *indices,
DirtyBits dirtyBitMask, DirtyBits dirtyBitMask,
...@@ -239,6 +240,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::CommandBuff ...@@ -239,6 +240,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::CommandBuff
angle::Result setupIndexedDraw(const gl::Context *context, angle::Result setupIndexedDraw(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
GLsizei indexCount, GLsizei indexCount,
GLsizei instanceCount,
gl::DrawElementsType indexType, gl::DrawElementsType indexType,
const void *indices, const void *indices,
vk::CommandBuffer **commandBufferOut); vk::CommandBuffer **commandBufferOut);
......
...@@ -74,38 +74,24 @@ bool ShouldEnableMockICD(const egl::AttributeMap &attribs) ...@@ -74,38 +74,24 @@ bool ShouldEnableMockICD(const egl::AttributeMap &attribs)
#endif // !defined(ANGLE_PLATFORM_ANDROID) #endif // !defined(ANGLE_PLATFORM_ANDROID)
} }
VkResult VerifyExtensionsPresent(const std::vector<VkExtensionProperties> &extensionProps, bool StrLess(const char *a, const char *b)
const std::vector<const char *> &enabledExtensionNames)
{ {
// Compile the extensions names into a set. return strcmp(a, b) < 0;
std::set<std::string> extensionNames; }
for (const auto &extensionProp : extensionProps)
{
extensionNames.insert(extensionProp.extensionName);
}
for (const char *extensionName : enabledExtensionNames)
{
if (extensionNames.count(extensionName) == 0)
{
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
}
return VK_SUCCESS; VkResult VerifyExtensionsPresent(const RendererVk::ExtensionNameList &haystack,
const RendererVk::ExtensionNameList &needles)
{
// NOTE: The lists must be sorted.
return std::includes(haystack.begin(), haystack.end(), needles.begin(), needles.end(), StrLess)
? VK_SUCCESS
: VK_ERROR_EXTENSION_NOT_PRESENT;
} }
bool ExtensionFound(const char *extensionName, bool ExtensionFound(const char *needle, const RendererVk::ExtensionNameList &haystack)
const std::vector<VkExtensionProperties> &extensionProps)
{ {
for (const auto &extensionProp : extensionProps) // NOTE: The list must be sorted.
{ return std::binary_search(haystack.begin(), haystack.end(), needle, StrLess);
if (strcmp(extensionProp.extensionName, extensionName) == 0)
{
return true;
}
}
return false;
} }
// Array of Validation error/warning messages that will be ignored, should include bugID // Array of Validation error/warning messages that will be ignored, should include bugID
...@@ -513,6 +499,7 @@ RendererVk::RendererVk() ...@@ -513,6 +499,7 @@ RendererVk::RendererVk()
mPhysicalDevice(VK_NULL_HANDLE), mPhysicalDevice(VK_NULL_HANDLE),
mQueue(VK_NULL_HANDLE), mQueue(VK_NULL_HANDLE),
mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()), mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()),
mMaxVertexAttribDivisor(1),
mDevice(VK_NULL_HANDLE), mDevice(VK_NULL_HANDLE),
mLastCompletedQueueSerial(mQueueSerialFactory.generate()), mLastCompletedQueueSerial(mQueueSerialFactory.generate()),
mCurrentQueueSerial(mQueueSerialFactory.generate()), mCurrentQueueSerial(mQueueSerialFactory.generate()),
...@@ -664,16 +651,26 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk, ...@@ -664,16 +651,26 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
instanceExtensionProps.data() + previousExtensionCount)); instanceExtensionProps.data() + previousExtensionCount));
} }
std::vector<const char *> enabledInstanceExtensions; ExtensionNameList instanceExtensionNames;
if (!instanceExtensionProps.empty())
{
for (const VkExtensionProperties &i : instanceExtensionProps)
{
instanceExtensionNames.push_back(i.extensionName);
}
std::sort(instanceExtensionNames.begin(), instanceExtensionNames.end(), StrLess);
}
ExtensionNameList enabledInstanceExtensions;
enabledInstanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); enabledInstanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
enabledInstanceExtensions.push_back(wsiExtension); enabledInstanceExtensions.push_back(wsiExtension);
bool enableDebugUtils = bool enableDebugUtils =
mEnableValidationLayers && mEnableValidationLayers &&
ExtensionFound(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, instanceExtensionProps); ExtensionFound(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, instanceExtensionNames);
bool enableDebugReport = bool enableDebugReport =
mEnableValidationLayers && !enableDebugUtils && mEnableValidationLayers && !enableDebugUtils &&
ExtensionFound(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, instanceExtensionProps); ExtensionFound(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, instanceExtensionNames);
if (enableDebugUtils) if (enableDebugUtils)
{ {
...@@ -685,8 +682,16 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk, ...@@ -685,8 +682,16 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
} }
// Verify the required extensions are in the extension names set. Fail if not. // Verify the required extensions are in the extension names set. Fail if not.
std::sort(enabledInstanceExtensions.begin(), enabledInstanceExtensions.end(), StrLess);
ANGLE_VK_TRY(displayVk, ANGLE_VK_TRY(displayVk,
VerifyExtensionsPresent(instanceExtensionProps, enabledInstanceExtensions)); VerifyExtensionsPresent(instanceExtensionNames, enabledInstanceExtensions));
// Enable VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME if available.
if (ExtensionFound(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
instanceExtensionNames))
{
enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
VkApplicationInfo applicationInfo = {}; VkApplicationInfo applicationInfo = {};
applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
...@@ -767,6 +772,14 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk, ...@@ -767,6 +772,14 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
&mDebugReportCallback)); &mDebugReportCallback));
} }
if (std::find(enabledInstanceExtensions.begin(), enabledInstanceExtensions.end(),
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) !=
enabledInstanceExtensions.end())
{
InitGetPhysicalDeviceProperties2KHRFunctions(mInstance);
ASSERT(vkGetPhysicalDeviceProperties2KHR);
}
uint32_t physicalDeviceCount = 0; uint32_t physicalDeviceCount = 0;
ANGLE_VK_TRY(displayVk, vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, nullptr)); ANGLE_VK_TRY(displayVk, vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, nullptr));
ANGLE_VK_CHECK(displayVk, physicalDeviceCount > 0, VK_ERROR_INITIALIZATION_FAILED); ANGLE_VK_CHECK(displayVk, physicalDeviceCount > 0, VK_ERROR_INITIALIZATION_FAILED);
...@@ -882,10 +895,21 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF ...@@ -882,10 +895,21 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
deviceExtensionProps.data() + previousExtensionCount)); deviceExtensionProps.data() + previousExtensionCount));
} }
std::vector<const char *> enabledDeviceExtensions; ExtensionNameList deviceExtensionNames;
if (!deviceExtensionProps.empty())
{
ASSERT(deviceExtensionNames.size() <= deviceExtensionProps.size());
for (const VkExtensionProperties &prop : deviceExtensionProps)
{
deviceExtensionNames.push_back(prop.extensionName);
}
std::sort(deviceExtensionNames.begin(), deviceExtensionNames.end(), StrLess);
}
ExtensionNameList enabledDeviceExtensions;
enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
initFeatures(deviceExtensionProps); initFeatures(deviceExtensionNames);
mFeaturesInitialized = true; mFeaturesInitialized = true;
// Selectively enable KHR_MAINTENANCE1 to support viewport flipping. // Selectively enable KHR_MAINTENANCE1 to support viewport flipping.
...@@ -899,17 +923,21 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF ...@@ -899,17 +923,21 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
enabledDeviceExtensions.push_back(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME); enabledDeviceExtensions.push_back(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
} }
ANGLE_VK_TRY(displayVk, VerifyExtensionsPresent(deviceExtensionProps, enabledDeviceExtensions)); std::sort(enabledDeviceExtensions.begin(), enabledDeviceExtensions.end(), StrLess);
ANGLE_VK_TRY(displayVk, VerifyExtensionsPresent(deviceExtensionNames, enabledDeviceExtensions));
// Select additional features to be enabled // Select additional features to be enabled
VkPhysicalDeviceFeatures enabledFeatures = {}; VkPhysicalDeviceFeatures2KHR enabledFeatures = {};
enabledFeatures.inheritedQueries = mPhysicalDeviceFeatures.inheritedQueries; enabledFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
enabledFeatures.robustBufferAccess = mPhysicalDeviceFeatures.robustBufferAccess; enabledFeatures.features.inheritedQueries = mPhysicalDeviceFeatures.inheritedQueries;
enabledFeatures.features.robustBufferAccess = mPhysicalDeviceFeatures.robustBufferAccess;
VkDeviceQueueCreateInfo queueCreateInfo = {}; VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT divisorFeatures = {};
divisorFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
divisorFeatures.vertexAttributeInstanceRateDivisor = true;
float zeroPriority = 0.0f; float zeroPriority = 0.0f;
VkDeviceQueueCreateInfo queueCreateInfo = {};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.flags = 0; queueCreateInfo.flags = 0;
queueCreateInfo.queueFamilyIndex = queueFamilyIndex; queueCreateInfo.queueFamilyIndex = queueFamilyIndex;
...@@ -925,10 +953,34 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF ...@@ -925,10 +953,34 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
createInfo.pQueueCreateInfos = &queueCreateInfo; createInfo.pQueueCreateInfos = &queueCreateInfo;
createInfo.enabledLayerCount = enabledDeviceLayerNames.size(); createInfo.enabledLayerCount = enabledDeviceLayerNames.size();
createInfo.ppEnabledLayerNames = enabledDeviceLayerNames.data(); createInfo.ppEnabledLayerNames = enabledDeviceLayerNames.data();
if (vkGetPhysicalDeviceProperties2KHR &&
ExtensionFound(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, deviceExtensionNames))
{
enabledDeviceExtensions.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
enabledFeatures.pNext = &divisorFeatures;
VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT divisorProperties = {};
divisorProperties.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT;
VkPhysicalDeviceProperties2 deviceProperties = {};
deviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
deviceProperties.pNext = &divisorProperties;
vkGetPhysicalDeviceProperties2KHR(mPhysicalDevice, &deviceProperties);
mMaxVertexAttribDivisor = divisorProperties.maxVertexAttribDivisor;
createInfo.pNext = &enabledFeatures;
}
else
{
createInfo.pEnabledFeatures = &enabledFeatures.features;
}
createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledDeviceExtensions.size()); createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledDeviceExtensions.size());
createInfo.ppEnabledExtensionNames = createInfo.ppEnabledExtensionNames =
enabledDeviceExtensions.empty() ? nullptr : enabledDeviceExtensions.data(); enabledDeviceExtensions.empty() ? nullptr : enabledDeviceExtensions.data();
createInfo.pEnabledFeatures = &enabledFeatures;
ANGLE_VK_TRY(displayVk, vkCreateDevice(mPhysicalDevice, &createInfo, nullptr, &mDevice)); ANGLE_VK_TRY(displayVk, vkCreateDevice(mPhysicalDevice, &createInfo, nullptr, &mDevice));
...@@ -1073,7 +1125,7 @@ gl::Version RendererVk::getMaxSupportedESVersion() const ...@@ -1073,7 +1125,7 @@ gl::Version RendererVk::getMaxSupportedESVersion() const
return maxVersion; return maxVersion;
} }
void RendererVk::initFeatures(const std::vector<VkExtensionProperties> &deviceExtensionProps) void RendererVk::initFeatures(const ExtensionNameList &deviceExtensionNames)
{ {
// Use OpenGL line rasterization rules by default. // Use OpenGL line rasterization rules by default.
// TODO(jmadill): Fix Android support. http://anglebug.com/2830 // TODO(jmadill): Fix Android support. http://anglebug.com/2830
...@@ -1084,7 +1136,7 @@ void RendererVk::initFeatures(const std::vector<VkExtensionProperties> &deviceEx ...@@ -1084,7 +1136,7 @@ void RendererVk::initFeatures(const std::vector<VkExtensionProperties> &deviceEx
#endif // defined(ANGLE_PLATFORM_ANDROID) #endif // defined(ANGLE_PLATFORM_ANDROID)
if ((mPhysicalDeviceProperties.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) || if ((mPhysicalDeviceProperties.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) ||
ExtensionFound(VK_KHR_MAINTENANCE1_EXTENSION_NAME, deviceExtensionProps)) ExtensionFound(VK_KHR_MAINTENANCE1_EXTENSION_NAME, deviceExtensionNames))
{ {
// TODO(lucferron): Currently disabled on Intel only since many tests are failing and need // TODO(lucferron): Currently disabled on Intel only since many tests are failing and need
// investigation. http://anglebug.com/2728 // investigation. http://anglebug.com/2728
...@@ -1124,7 +1176,7 @@ void RendererVk::initFeatures(const std::vector<VkExtensionProperties> &deviceEx ...@@ -1124,7 +1176,7 @@ void RendererVk::initFeatures(const std::vector<VkExtensionProperties> &deviceEx
IsNexus5X(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID); IsNexus5X(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID);
#endif #endif
if (ExtensionFound(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, deviceExtensionProps)) if (ExtensionFound(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, deviceExtensionNames))
{ {
mFeatures.supportsIncrementalPresent = true; mFeatures.supportsIncrementalPresent = true;
} }
......
...@@ -205,6 +205,9 @@ class RendererVk : angle::NonCopyable ...@@ -205,6 +205,9 @@ class RendererVk : angle::NonCopyable
bool hasTextureFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits); bool hasTextureFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits);
bool hasBufferFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits); bool hasBufferFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits);
static constexpr size_t kMaxExtensionNames = 200;
using ExtensionNameList = angle::FixedVector<const char *, kMaxExtensionNames>;
private: private:
// Number of semaphores for external entities to renderer to issue a wait, such as surface's // Number of semaphores for external entities to renderer to issue a wait, such as surface's
// image acquire. // image acquire.
...@@ -224,7 +227,7 @@ class RendererVk : angle::NonCopyable ...@@ -224,7 +227,7 @@ class RendererVk : angle::NonCopyable
vk::CommandBuffer &&commandBuffer); vk::CommandBuffer &&commandBuffer);
void freeAllInFlightResources(); void freeAllInFlightResources();
angle::Result flushCommandGraph(vk::Context *context, vk::CommandBuffer *commandBatch); angle::Result flushCommandGraph(vk::Context *context, vk::CommandBuffer *commandBatch);
void initFeatures(const std::vector<VkExtensionProperties> &deviceExtensionProps); void initFeatures(const ExtensionNameList &extensions);
void initPipelineCacheVkKey(); void initPipelineCacheVkKey();
angle::Result initPipelineCache(DisplayVk *display); angle::Result initPipelineCache(DisplayVk *display);
...@@ -262,6 +265,7 @@ class RendererVk : angle::NonCopyable ...@@ -262,6 +265,7 @@ class RendererVk : angle::NonCopyable
std::vector<VkQueueFamilyProperties> mQueueFamilyProperties; std::vector<VkQueueFamilyProperties> mQueueFamilyProperties;
VkQueue mQueue; VkQueue mQueue;
uint32_t mCurrentQueueFamilyIndex; uint32_t mCurrentQueueFamilyIndex;
uint32_t mMaxVertexAttribDivisor;
VkDevice mDevice; VkDevice mDevice;
vk::CommandPool mCommandPool; vk::CommandPool mCommandPool;
SerialFactory mQueueSerialFactory; SerialFactory mQueueSerialFactory;
......
...@@ -492,6 +492,7 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk, ...@@ -492,6 +492,7 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context, angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context,
GLint firstVertex, GLint firstVertex,
GLsizei vertexOrIndexCount, GLsizei vertexOrIndexCount,
GLsizei instanceCount,
gl::DrawElementsType indexTypeOrInvalid, gl::DrawElementsType indexTypeOrInvalid,
const void *indices) const void *indices)
{ {
...@@ -522,22 +523,35 @@ angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context, ...@@ -522,22 +523,35 @@ angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context,
const vk::Format &vertexFormat = renderer->getFormat(GetVertexFormatID(attrib)); const vk::Format &vertexFormat = renderer->getFormat(GetVertexFormatID(attrib));
GLuint stride = vertexFormat.bufferFormat().pixelBytes; GLuint stride = vertexFormat.bufferFormat().pixelBytes;
const size_t bytesToAllocate = (startVertex + vertexCount) * stride; ASSERT(GetVertexInputAlignment(vertexFormat) <= kMaxVertexFormatAlignment);
const uint8_t *src =
static_cast<const uint8_t *>(attrib.pointer) + startVertex * binding.getStride(); const uint8_t *src = static_cast<const uint8_t *>(attrib.pointer);
if (binding.getDivisor() > 0)
{
// instanced attrib
size_t count = UnsignedCeilDivide(instanceCount, binding.getDivisor());
size_t bytesToAllocate = count * stride;
ANGLE_TRY(StreamVertexData(contextVk, &mDynamicVertexData, src, bytesToAllocate, 0,
count, binding.getStride(), vertexFormat.vertexLoadFunction,
&mCurrentArrayBuffers[attribIndex],
&mCurrentArrayBufferOffsets[attribIndex]));
}
else
{
// Allocate space for startVertex + vertexCount so indexing will work. If we don't
// start at zero all the indices will be off.
// Only vertexCount vertices will be used by the upcoming draw so that is all we copy.
size_t bytesToAllocate = (startVertex + vertexCount) * stride;
src += startVertex * binding.getStride();
size_t destOffset = startVertex * stride; size_t destOffset = startVertex * stride;
ASSERT(GetVertexInputAlignment(vertexFormat) <= kMaxVertexFormatAlignment);
// Only vertexCount() vertices will be used by the upcoming draw. so that is all we copy.
// We allocate space for startVertex + vertexCount so indexing will work. If we
// don't start at zero all the indices will be off.
// TODO(fjhenigman): See if we can account for indices being off by adjusting the
// offset, thus avoiding wasted memory.
ANGLE_TRY(StreamVertexData( ANGLE_TRY(StreamVertexData(
contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount, contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount,
binding.getStride(), vertexFormat.vertexLoadFunction, binding.getStride(), vertexFormat.vertexLoadFunction,
&mCurrentArrayBuffers[attribIndex], &mCurrentArrayBufferOffsets[attribIndex])); &mCurrentArrayBuffers[attribIndex], &mCurrentArrayBufferOffsets[attribIndex]));
}
mCurrentArrayBufferHandles[attribIndex] = mCurrentArrayBufferHandles[attribIndex] =
mCurrentArrayBuffers[attribIndex]->getBuffer().getHandle(); mCurrentArrayBuffers[attribIndex]->getBuffer().getHandle();
} }
......
...@@ -39,6 +39,7 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -39,6 +39,7 @@ class VertexArrayVk : public VertexArrayImpl
angle::Result updateClientAttribs(const gl::Context *context, angle::Result updateClientAttribs(const gl::Context *context,
GLint firstVertex, GLint firstVertex,
GLsizei vertexOrIndexCount, GLsizei vertexOrIndexCount,
GLsizei instanceCount,
gl::DrawElementsType indexTypeOrInvalid, gl::DrawElementsType indexTypeOrInvalid,
const void *indices); const void *indices);
......
...@@ -536,6 +536,11 @@ angle::Result GraphicsPipelineDesc::initializePipeline( ...@@ -536,6 +536,11 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
sizeof(attributeDescs); sizeof(attributeDescs);
ANGLE_UNUSED_VARIABLE(unpackedSize); ANGLE_UNUSED_VARIABLE(unpackedSize);
gl::AttribArray<VkVertexInputBindingDivisorDescriptionEXT> divisorDesc;
VkPipelineVertexInputDivisorStateCreateInfoEXT divisorState = {};
divisorState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
divisorState.pVertexBindingDivisors = divisorDesc.data();
for (size_t attribIndexSizeT : activeAttribLocationsMask) for (size_t attribIndexSizeT : activeAttribLocationsMask)
{ {
const uint32_t attribIndex = static_cast<uint32_t>(attribIndexSizeT); const uint32_t attribIndex = static_cast<uint32_t>(attribIndexSizeT);
...@@ -545,8 +550,18 @@ angle::Result GraphicsPipelineDesc::initializePipeline( ...@@ -545,8 +550,18 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
const PackedAttribDesc &packedAttrib = mVertexInputAttribs.attribs[attribIndex]; const PackedAttribDesc &packedAttrib = mVertexInputAttribs.attribs[attribIndex];
bindingDesc.binding = attribIndex; bindingDesc.binding = attribIndex;
bindingDesc.inputRate = static_cast<VkVertexInputRate>(packedAttrib.inputRate);
bindingDesc.stride = static_cast<uint32_t>(packedAttrib.stride); bindingDesc.stride = static_cast<uint32_t>(packedAttrib.stride);
if (packedAttrib.divisor != 0)
{
bindingDesc.inputRate = static_cast<VkVertexInputRate>(VK_VERTEX_INPUT_RATE_INSTANCE);
divisorDesc[divisorState.vertexBindingDivisorCount].binding = bindingDesc.binding;
divisorDesc[divisorState.vertexBindingDivisorCount].divisor = packedAttrib.divisor;
++divisorState.vertexBindingDivisorCount;
}
else
{
bindingDesc.inputRate = static_cast<VkVertexInputRate>(VK_VERTEX_INPUT_RATE_VERTEX);
}
// The binding index could become more dynamic in ES 3.1. // The binding index could become more dynamic in ES 3.1.
attribDesc.binding = attribIndex; attribDesc.binding = attribIndex;
...@@ -564,6 +579,8 @@ angle::Result GraphicsPipelineDesc::initializePipeline( ...@@ -564,6 +579,8 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
vertexInputState.pVertexBindingDescriptions = bindingDescs.data(); vertexInputState.pVertexBindingDescriptions = bindingDescs.data();
vertexInputState.vertexAttributeDescriptionCount = vertexAttribCount; vertexInputState.vertexAttributeDescriptionCount = vertexAttribCount;
vertexInputState.pVertexAttributeDescriptions = attributeDescs.data(); vertexInputState.pVertexAttributeDescriptions = attributeDescs.data();
if (divisorState.vertexBindingDivisorCount)
vertexInputState.pNext = &divisorState;
// Primitive topology is filled in at draw time. // Primitive topology is filled in at draw time.
inputAssemblyState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; inputAssemblyState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
...@@ -696,12 +713,12 @@ void GraphicsPipelineDesc::updateVertexInput(GraphicsPipelineTransitionBits *tra ...@@ -696,12 +713,12 @@ void GraphicsPipelineDesc::updateVertexInput(GraphicsPipelineTransitionBits *tra
{ {
vk::PackedAttribDesc &packedAttrib = mVertexInputAttribs.attribs[attribIndex]; vk::PackedAttribDesc &packedAttrib = mVertexInputAttribs.attribs[attribIndex];
// TODO(http://anglebug.com/2672): This will need to be updated to support instancing. // TODO: Handle the case where the divisor overflows the field that holds it.
ASSERT(divisor == 0); // http://anglebug.com/2672
ASSERT(divisor <= std::numeric_limits<decltype(packedAttrib.divisor)>::max());
SetBitField(packedAttrib.stride, stride); SetBitField(packedAttrib.stride, stride);
SetBitField(packedAttrib.inputRate, SetBitField(packedAttrib.divisor, divisor);
divisor > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
if (format == VK_FORMAT_UNDEFINED) if (format == VK_FORMAT_UNDEFINED)
{ {
......
...@@ -128,9 +128,8 @@ struct PackedAttribDesc final ...@@ -128,9 +128,8 @@ struct PackedAttribDesc final
{ {
uint8_t format; uint8_t format;
// inputRate can also be used to store instancing divisors up to 255.
// TODO(http://anglebug.com/2672): Emulate divisors greater than UBYTE_MAX. // TODO(http://anglebug.com/2672): Emulate divisors greater than UBYTE_MAX.
uint8_t inputRate; uint8_t divisor;
// Can only take 11 bits on NV. // Can only take 11 bits on NV.
uint16_t offset; uint16_t offset;
......
...@@ -56,6 +56,10 @@ void RendererVk::ensureCapsInitialized() const ...@@ -56,6 +56,10 @@ void RendererVk::ensureCapsInitialized() const
// TODO(geofflang): Support GL_OES_EGL_image_external_essl3. http://anglebug.com/2668 // TODO(geofflang): Support GL_OES_EGL_image_external_essl3. http://anglebug.com/2668
mNativeExtensions.eglImageExternalEssl3 = false; mNativeExtensions.eglImageExternalEssl3 = false;
// TODO: Enable this always and emulate instanced draws if any divisor exceeds the maximum
// supported. http://anglebug.com/2672
mNativeExtensions.instancedArraysANGLE = mMaxVertexAttribDivisor > 1;
// Only expose robust buffer access if the physical device supports it. // Only expose robust buffer access if the physical device supports it.
mNativeExtensions.robustBufferAccessBehavior = mPhysicalDeviceFeatures.robustBufferAccess; mNativeExtensions.robustBufferAccessBehavior = mPhysicalDeviceFeatures.robustBufferAccess;
......
...@@ -30,17 +30,6 @@ struct FeaturesVk; ...@@ -30,17 +30,6 @@ struct FeaturesVk;
class DisplayVk; class DisplayVk;
namespace vk
{
void GenerateCaps(const VkPhysicalDeviceProperties &physicalDeviceProperties,
const VkPhysicalDeviceFeatures &physicalDeviceFeatures,
const VkQueueFamilyProperties &queueFamilyProperties,
const gl::TextureCapsMap &textureCaps,
gl::Caps *outCaps,
gl::Extensions *outExtensions,
gl::Limitations * /* outLimitations */);
} // namespace vk
namespace egl_vk namespace egl_vk
{ {
constexpr GLenum kConfigDepthStencilFormats[] = {GL_NONE, GL_DEPTH24_STENCIL8, GL_DEPTH_COMPONENT24, constexpr GLenum kConfigDepthStencilFormats[] = {GL_NONE, GL_DEPTH24_STENCIL8, GL_DEPTH_COMPONENT24,
......
...@@ -480,6 +480,9 @@ PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = nullptr; ...@@ -480,6 +480,9 @@ PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = nullptr;
PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = nullptr; PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = nullptr;
PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT = nullptr; PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT = nullptr;
// VK_KHR_get_physical_device_properties2
PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR = nullptr;
#if defined(ANGLE_PLATFORM_FUCHSIA) #if defined(ANGLE_PLATFORM_FUCHSIA)
// VK_FUCHSIA_imagepipe_surface // VK_FUCHSIA_imagepipe_surface
PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA = nullptr; PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA = nullptr;
...@@ -504,6 +507,11 @@ void InitDebugReportEXTFunctions(VkInstance instance) ...@@ -504,6 +507,11 @@ void InitDebugReportEXTFunctions(VkInstance instance)
GET_FUNC(vkDestroyDebugReportCallbackEXT); GET_FUNC(vkDestroyDebugReportCallbackEXT);
} }
void InitGetPhysicalDeviceProperties2KHRFunctions(VkInstance instance)
{
GET_FUNC(vkGetPhysicalDeviceProperties2KHR);
}
#if defined(ANGLE_PLATFORM_FUCHSIA) #if defined(ANGLE_PLATFORM_FUCHSIA)
void InitImagePipeSurfaceFUCHSIAFunctions(VkInstance instance) void InitImagePipeSurfaceFUCHSIAFunctions(VkInstance instance)
{ {
......
...@@ -387,9 +387,13 @@ extern PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT; ...@@ -387,9 +387,13 @@ extern PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT;
extern PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT; extern PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
extern PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT; extern PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
// VK_KHR_get_physical_device_properties2
extern PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
// Lazily load entry points for each extension as necessary. // Lazily load entry points for each extension as necessary.
void InitDebugUtilsEXTFunctions(VkInstance instance); void InitDebugUtilsEXTFunctions(VkInstance instance);
void InitDebugReportEXTFunctions(VkInstance instance); void InitDebugReportEXTFunctions(VkInstance instance);
void InitGetPhysicalDeviceProperties2KHRFunctions(VkInstance instance);
#if defined(ANGLE_PLATFORM_FUCHSIA) #if defined(ANGLE_PLATFORM_FUCHSIA)
// VK_FUCHSIA_imagepipe_surface // VK_FUCHSIA_imagepipe_surface
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment