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)
{ {
ANGLE_VK_UNREACHABLE(this); if (mode == gl::PrimitiveMode::LineLoop)
return angle::Result::Stop; {
// TODO - http://anglebug.com/2672
ANGLE_VK_UNREACHABLE(this);
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)
{ {
ANGLE_VK_UNREACHABLE(this); if (mode == gl::PrimitiveMode::LineLoop)
return angle::Result::Stop; {
// TODO - http://anglebug.com/2672
ANGLE_VK_UNREACHABLE(this);
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);
......
...@@ -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;
const uint8_t *src =
static_cast<const uint8_t *>(attrib.pointer) + startVertex * binding.getStride();
size_t destOffset = startVertex * stride;
ASSERT(GetVertexInputAlignment(vertexFormat) <= kMaxVertexFormatAlignment); ASSERT(GetVertexInputAlignment(vertexFormat) <= kMaxVertexFormatAlignment);
// Only vertexCount() vertices will be used by the upcoming draw. so that is all we copy. const uint8_t *src = static_cast<const uint8_t *>(attrib.pointer);
// We allocate space for startVertex + vertexCount so indexing will work. If we if (binding.getDivisor() > 0)
// 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 // instanced attrib
// offset, thus avoiding wasted memory. size_t count = UnsignedCeilDivide(instanceCount, binding.getDivisor());
ANGLE_TRY(StreamVertexData( size_t bytesToAllocate = count * stride;
contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount,
binding.getStride(), vertexFormat.vertexLoadFunction, ANGLE_TRY(StreamVertexData(contextVk, &mDynamicVertexData, src, bytesToAllocate, 0,
&mCurrentArrayBuffers[attribIndex], &mCurrentArrayBufferOffsets[attribIndex])); 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;
ANGLE_TRY(StreamVertexData(
contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount,
binding.getStride(), vertexFormat.vertexLoadFunction,
&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