Commit f03259ad by Courtney Goeltzenleuchter Committed by Commit Bot

Vulkan: lineloop support for DrawElementsIndirect

Add support for lineloops. Includes a compute shader for converting lineloop index buffer with optional restart into linestrip. Test: dEQP.GLES31/functional_draw_indirect_* angle_end2end_tests --gtest_filter=LineLoopIndirectTest.*/* Bug: angleproject:3564 Change-Id: I12d08db1c8d99867f0611e53be50193647695260 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1797106 Commit-Queue: Courtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarTobin Ehlis <tobine@google.com>
parent e5009be8
...@@ -89,6 +89,10 @@ ...@@ -89,6 +89,10 @@
"db98380613bc3f032037b4a096756975", "db98380613bc3f032037b4a096756975",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000003.inc": "src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000003.inc":
"e676bdff5c3b596eccba13a4e52d3875", "e676bdff5c3b596eccba13a4e52d3875",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndexIndirectLineLoop.comp.00000000.inc":
"d99b638b0b2efa9726350869fe6b9b10",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndexIndirectLineLoop.comp.00000001.inc":
"8f27f7634724189ce2bd63820e96ee63",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000000.inc": "src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000000.inc":
"f5ef892346ee10e5d0d9f8cba2a491b2", "f5ef892346ee10e5d0d9f8cba2a491b2",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000001.inc": "src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000001.inc":
...@@ -287,6 +291,8 @@ ...@@ -287,6 +291,8 @@
"b7c20e019199f8328ef37b11c6fbcadd", "b7c20e019199f8328ef37b11c6fbcadd",
"src/libANGLE/renderer/vulkan/shaders/src/ConvertIndex.comp": "src/libANGLE/renderer/vulkan/shaders/src/ConvertIndex.comp":
"083e2b6ed2cf40f036287413c449e675", "083e2b6ed2cf40f036287413c449e675",
"src/libANGLE/renderer/vulkan/shaders/src/ConvertIndexIndirectLineLoop.comp":
"a543a28fc1fe53eefd5949ee3b4428f3",
"src/libANGLE/renderer/vulkan/shaders/src/ConvertVertex.comp": "src/libANGLE/renderer/vulkan/shaders/src/ConvertVertex.comp":
"88d434e43a01906e6a6b1dd5d5e45cdc", "88d434e43a01906e6a6b1dd5d5e45cdc",
"src/libANGLE/renderer/vulkan/shaders/src/FullScreenQuad.vert": "src/libANGLE/renderer/vulkan/shaders/src/FullScreenQuad.vert":
...@@ -300,9 +306,9 @@ ...@@ -300,9 +306,9 @@
"src/libANGLE/renderer/vulkan/shaders/src/OverlayDraw.comp": "src/libANGLE/renderer/vulkan/shaders/src/OverlayDraw.comp":
"dcc246b398b2e07a869a264666499362", "dcc246b398b2e07a869a264666499362",
"src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp": "src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp":
"24c8e4c95087419916f879a8c7976213", "39bcc07efd2fe05c1eb0a9d9e34567d3",
"src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h": "src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h":
"2ee06bb4c179bcdcd4863396c43776a9", "cfeb07579c1ba5051450f76f06e47d05",
"tools/glslang/glslang_validator.exe.sha1": "tools/glslang/glslang_validator.exe.sha1":
"289f30598865a987a21b79ae525fc66f", "289f30598865a987a21b79ae525fc66f",
"tools/glslang/glslang_validator.sha1": "tools/glslang/glslang_validator.sha1":
......
...@@ -899,6 +899,40 @@ angle::Result ContextVk::setupIndexedIndirectDraw(const gl::Context *context, ...@@ -899,6 +899,40 @@ angle::Result ContextVk::setupIndexedIndirectDraw(const gl::Context *context,
indirectBufferOut); indirectBufferOut);
} }
angle::Result ContextVk::setupLineLoopIndexedIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode,
gl::DrawElementsType indexType,
const gl::Buffer *indirectBuffer,
VkDeviceSize indirectBufferOffset,
const gl::Buffer *indexBuffer,
vk::CommandBuffer **commandBufferOut,
vk::Buffer **indirectBufferOut,
VkDeviceSize *indirectBufferOffsetOut)
{
ASSERT(mode == gl::PrimitiveMode::LineLoop);
BufferVk *indirectBufferVk = vk::GetImpl(indirectBuffer);
vk::BufferHelper *indirectBufferHelperOut = nullptr;
ANGLE_TRY(mVertexArray->handleLineLoopIndirect(this, indirectBufferVk, indexType,
indirectBufferOffset, &indirectBufferHelperOut,
indirectBufferOffsetOut));
*indirectBufferOut = const_cast<vk::Buffer *>(&indirectBufferHelperOut->getBuffer());
if (indexType != mCurrentDrawElementsType)
{
mCurrentDrawElementsType = indexType;
setIndexBufferDirty();
}
vk::FramebufferHelper *framebuffer = mDrawFramebuffer->getFramebuffer();
indirectBufferHelperOut->onRead(this, framebuffer, VK_ACCESS_INDIRECT_COMMAND_READ_BIT);
return setupDraw(context, mode, -1, 0, 0, gl::DrawElementsType::InvalidEnum, nullptr,
mIndexedDirtyBitsMask, commandBufferOut);
}
angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context, angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
GLint firstVertex, GLint firstVertex,
...@@ -1719,7 +1753,8 @@ angle::Result ContextVk::drawElementsIndirect(const gl::Context *context, ...@@ -1719,7 +1753,8 @@ angle::Result ContextVk::drawElementsIndirect(const gl::Context *context,
gl::DrawElementsType type, gl::DrawElementsType type,
const void *indirect) const void *indirect)
{ {
gl::Buffer *indirectBuffer = mState.getTargetBuffer(gl::BufferBinding::DrawIndirect); VkDeviceSize indirectBufferOffset = reinterpret_cast<VkDeviceSize>(indirect);
gl::Buffer *indirectBuffer = mState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
ASSERT(indirectBuffer); ASSERT(indirectBuffer);
const gl::Buffer *indexBuffer = mVertexArray->getState().getElementArrayBuffer(); const gl::Buffer *indexBuffer = mVertexArray->getState().getElementArrayBuffer();
...@@ -1734,18 +1769,21 @@ angle::Result ContextVk::drawElementsIndirect(const gl::Context *context, ...@@ -1734,18 +1769,21 @@ angle::Result ContextVk::drawElementsIndirect(const gl::Context *context,
} }
vk::CommandBuffer *commandBuffer = nullptr; vk::CommandBuffer *commandBuffer = nullptr;
vk::Buffer *buffer = nullptr; vk::Buffer *indirectBufferFinal = nullptr;
ANGLE_TRY(setupIndexedIndirectDraw(context, mode, type, &commandBuffer, &buffer));
if (mode == gl::PrimitiveMode::LineLoop) if (mode == gl::PrimitiveMode::LineLoop)
{ {
// TODO - http://anglebug.com/3564 ANGLE_TRY(setupLineLoopIndexedIndirectDraw(
ANGLE_VK_UNREACHABLE(this); context, mode, type, indirectBuffer, indirectBufferOffset, indexBuffer, &commandBuffer,
return angle::Result::Stop; &indirectBufferFinal, &indirectBufferOffset));
}
else
{
ANGLE_TRY(
setupIndexedIndirectDraw(context, mode, type, &commandBuffer, &indirectBufferFinal));
} }
commandBuffer->drawIndexedIndirect(*buffer, reinterpret_cast<VkDeviceSize>(indirect), 1, 0); commandBuffer->drawIndexedIndirect(*indirectBufferFinal, indirectBufferOffset, 1, 0);
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -507,12 +507,26 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO ...@@ -507,12 +507,26 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
DirtyBits dirtyBitMask, DirtyBits dirtyBitMask,
vk::CommandBuffer **commandBufferOut, vk::CommandBuffer **commandBufferOut,
vk::Buffer **indirectBufferOut); vk::Buffer **indirectBufferOut);
angle::Result setupIndirectDrawHelper(const gl::Context *context,
gl::PrimitiveMode mode,
DirtyBits dirtyBitMask,
vk::CommandBuffer **commandBufferOut);
angle::Result setupIndexedIndirectDraw(const gl::Context *context, angle::Result setupIndexedIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
gl::DrawElementsType indexType, gl::DrawElementsType indexType,
vk::CommandBuffer **commandBufferOut, vk::CommandBuffer **commandBufferOut,
vk::Buffer **indirectBufferOut); vk::Buffer **indirectBufferOut);
angle::Result setupLineLoopIndexedIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode,
gl::DrawElementsType indexType,
const gl::Buffer *indirectBuffer,
VkDeviceSize indirectBufferOffset,
const gl::Buffer *indexBuffer,
vk::CommandBuffer **commandBufferOut,
vk::Buffer **indirectBufferOut,
VkDeviceSize *indirectBufferOffsetOut);
angle::Result setupLineLoopDraw(const gl::Context *context, angle::Result setupLineLoopDraw(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
GLint firstVertex, GLint firstVertex,
......
...@@ -526,6 +526,25 @@ angle::Result UtilsVk::ensureConvertIndexIndirectResourcesInitialized(ContextVk ...@@ -526,6 +526,25 @@ angle::Result UtilsVk::ensureConvertIndexIndirectResourcesInitialized(ContextVk
sizeof(ConvertIndexIndirectShaderParams)); sizeof(ConvertIndexIndirectShaderParams));
} }
angle::Result UtilsVk::ensureConvertIndexIndirectLineLoopResourcesInitialized(ContextVk *contextVk)
{
if (mPipelineLayouts[Function::ConvertIndexIndirectLineLoopBuffer].valid())
{
return angle::Result::Continue;
}
VkDescriptorPoolSize setSizes[4] = {
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // cmd buffer
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // dest cmd buffer
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // source index buffer
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // dest index buffer
};
return ensureResourcesInitialized(contextVk, Function::ConvertIndexIndirectLineLoopBuffer,
setSizes, ArraySize(setSizes),
sizeof(ConvertIndexIndirectLineLoopShaderParams));
}
angle::Result UtilsVk::ensureConvertVertexResourcesInitialized(ContextVk *contextVk) angle::Result UtilsVk::ensureConvertVertexResourcesInitialized(ContextVk *contextVk)
{ {
if (mPipelineLayouts[Function::ConvertVertexBuffer].valid()) if (mPipelineLayouts[Function::ConvertVertexBuffer].valid())
...@@ -922,6 +941,77 @@ angle::Result UtilsVk::convertIndexIndirectBuffer(ContextVk *contextVk, ...@@ -922,6 +941,77 @@ angle::Result UtilsVk::convertIndexIndirectBuffer(ContextVk *contextVk,
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result UtilsVk::convertLineLoopIndexIndirectBuffer(
ContextVk *contextVk,
vk::BufferHelper *srcIndirectBuffer,
vk::BufferHelper *destIndirectBuffer,
vk::BufferHelper *destIndexBuffer,
vk::BufferHelper *srcIndexBuffer,
const ConvertLineLoopIndexIndirectParameters &params)
{
ANGLE_TRY(ensureConvertIndexIndirectLineLoopResourcesInitialized(contextVk));
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(destIndexBuffer->recordCommands(contextVk, &commandBuffer));
// Tell src we are going to read from it and dest it's being written to.
srcIndexBuffer->onReadByBuffer(contextVk, destIndexBuffer, VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_SHADER_WRITE_BIT);
srcIndirectBuffer->onReadByBuffer(contextVk, destIndexBuffer, VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_SHADER_WRITE_BIT);
ANGLE_TRY(destIndirectBuffer->recordCommands(contextVk, &commandBuffer));
srcIndirectBuffer->onReadByBuffer(contextVk, destIndirectBuffer, VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_SHADER_WRITE_BIT);
VkDescriptorSet descriptorSet;
vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertIndexIndirectLineLoopBuffer,
&descriptorPoolBinding, &descriptorSet));
std::array<VkDescriptorBufferInfo, 4> buffers = {{
{srcIndirectBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
{destIndirectBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
{destIndexBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
{srcIndexBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
}};
VkWriteDescriptorSet writeInfo = {};
writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeInfo.dstSet = descriptorSet;
writeInfo.dstBinding = kConvertIndexDestinationBinding;
writeInfo.descriptorCount = 4;
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
writeInfo.pBufferInfo = buffers.data();
vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
ConvertIndexIndirectLineLoopShaderParams shaderParams = {
params.indirectBufferOffset >> 2, params.dstIndirectBufferOffset >> 2,
params.dstIndexBufferOffset >> 2, contextVk->getState().isPrimitiveRestartEnabled()};
uint32_t flags = 0;
if (params.is32Bit)
{
flags |= vk::InternalShader::ConvertIndexIndirectLineLoop_comp::kIs32Bit;
}
vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndexIndirectLineLoop_comp(contextVk, flags,
&shader));
ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexIndirectLineLoopBuffer, shader, nullptr,
&mConvertIndexPrograms[flags], nullptr, descriptorSet, &shaderParams,
sizeof(ConvertIndexIndirectLineLoopShaderParams), commandBuffer));
commandBuffer->dispatch(1, 1, 1);
descriptorPoolBinding.reset();
return angle::Result::Continue;
}
angle::Result UtilsVk::convertVertexBuffer(ContextVk *contextVk, angle::Result UtilsVk::convertVertexBuffer(ContextVk *contextVk,
vk::BufferHelper *dest, vk::BufferHelper *dest,
vk::BufferHelper *src, vk::BufferHelper *src,
......
...@@ -61,6 +61,14 @@ class UtilsVk : angle::NonCopyable ...@@ -61,6 +61,14 @@ class UtilsVk : angle::NonCopyable
uint32_t maxIndex = 0; uint32_t maxIndex = 0;
}; };
struct ConvertLineLoopIndexIndirectParameters
{
uint32_t indirectBufferOffset = 0;
uint32_t dstIndirectBufferOffset = 0;
uint32_t dstIndexBufferOffset = 0;
uint32_t is32Bit = 0;
};
struct ConvertVertexParameters struct ConvertVertexParameters
{ {
size_t vertexCount; size_t vertexCount;
...@@ -94,7 +102,8 @@ class UtilsVk : angle::NonCopyable ...@@ -94,7 +102,8 @@ class UtilsVk : angle::NonCopyable
struct BlitResolveParameters struct BlitResolveParameters
{ {
// |srcOffset| and |dstOffset| define the original blit/resolve offsets, possibly flipped. // |srcOffset| and |dstIndexBufferOffset| define the original blit/resolve offsets, possibly
// flipped.
int srcOffset[2]; int srcOffset[2];
int destOffset[2]; int destOffset[2];
// |stretch| is SourceDimension / DestDimension used to transfer dest coordinates to source. // |stretch| is SourceDimension / DestDimension used to transfer dest coordinates to source.
...@@ -150,6 +159,14 @@ class UtilsVk : angle::NonCopyable ...@@ -150,6 +159,14 @@ class UtilsVk : angle::NonCopyable
vk::BufferHelper *src, vk::BufferHelper *src,
const ConvertIndexIndirectParameters &params); const ConvertIndexIndirectParameters &params);
angle::Result convertLineLoopIndexIndirectBuffer(
ContextVk *contextVk,
vk::BufferHelper *cmdBufferVk,
vk::BufferHelper *destCmdBufferVk,
vk::BufferHelper *dest,
vk::BufferHelper *src,
const ConvertLineLoopIndexIndirectParameters &params);
angle::Result convertVertexBuffer(ContextVk *contextVk, angle::Result convertVertexBuffer(ContextVk *contextVk,
vk::BufferHelper *dest, vk::BufferHelper *dest,
vk::BufferHelper *src, vk::BufferHelper *src,
...@@ -231,6 +248,14 @@ class UtilsVk : angle::NonCopyable ...@@ -231,6 +248,14 @@ class UtilsVk : angle::NonCopyable
uint32_t _padding = 0; uint32_t _padding = 0;
}; };
struct ConvertIndexIndirectLineLoopShaderParams
{
uint32_t cmdOffsetDiv4 = 0;
uint32_t dstCmdOffsetDiv4 = 0;
uint32_t dstOffsetDiv4 = 0;
uint32_t isRestartEnabled = 0;
};
struct ConvertVertexShaderParams struct ConvertVertexShaderParams
{ {
ConvertVertexShaderParams(); ConvertVertexShaderParams();
...@@ -332,9 +357,10 @@ class UtilsVk : angle::NonCopyable ...@@ -332,9 +357,10 @@ class UtilsVk : angle::NonCopyable
OverlayCull = 7, OverlayCull = 7,
OverlayDraw = 8, OverlayDraw = 8,
ConvertIndexIndirectBuffer = 9, ConvertIndexIndirectBuffer = 9,
ConvertIndexIndirectLineLoopBuffer = 10,
InvalidEnum = 10, InvalidEnum = 11,
EnumCount = 10, EnumCount = 11,
}; };
// Common function that creates the pipeline for the specified function, binds it and prepares // Common function that creates the pipeline for the specified function, binds it and prepares
...@@ -369,6 +395,7 @@ class UtilsVk : angle::NonCopyable ...@@ -369,6 +395,7 @@ class UtilsVk : angle::NonCopyable
angle::Result ensureBufferClearResourcesInitialized(ContextVk *contextVk); angle::Result ensureBufferClearResourcesInitialized(ContextVk *contextVk);
angle::Result ensureConvertIndexResourcesInitialized(ContextVk *contextVk); angle::Result ensureConvertIndexResourcesInitialized(ContextVk *contextVk);
angle::Result ensureConvertIndexIndirectResourcesInitialized(ContextVk *contextVk); angle::Result ensureConvertIndexIndirectResourcesInitialized(ContextVk *contextVk);
angle::Result ensureConvertIndexIndirectLineLoopResourcesInitialized(ContextVk *contextVk);
angle::Result ensureConvertVertexResourcesInitialized(ContextVk *contextVk); angle::Result ensureConvertVertexResourcesInitialized(ContextVk *contextVk);
angle::Result ensureImageClearResourcesInitialized(ContextVk *contextVk); angle::Result ensureImageClearResourcesInitialized(ContextVk *contextVk);
angle::Result ensureImageCopyResourcesInitialized(ContextVk *contextVk); angle::Result ensureImageCopyResourcesInitialized(ContextVk *contextVk);
......
...@@ -214,6 +214,21 @@ angle::Result VertexArrayVk::convertIndexBufferIndirectGPU(ContextVk *contextVk, ...@@ -214,6 +214,21 @@ angle::Result VertexArrayVk::convertIndexBufferIndirectGPU(ContextVk *contextVk,
dest, src, params); dest, src, params);
} }
angle::Result VertexArrayVk::handleLineLoopIndirect(ContextVk *contextVk,
BufferVk *indirectBufferVk,
gl::DrawElementsType glIndexType,
VkDeviceSize indirectBufferOffset,
vk::BufferHelper **indirectBufferOut,
VkDeviceSize *indirectBufferOffsetOut)
{
ANGLE_TRY(mLineLoopHelper.streamIndicesIndirect(
contextVk, glIndexType, mCurrentElementArrayBuffer, &indirectBufferVk->getBuffer(),
indirectBufferOffset, &mCurrentElementArrayBuffer, &mCurrentElementArrayBufferOffset,
indirectBufferOut, indirectBufferOffsetOut));
return angle::Result::Continue;
}
angle::Result VertexArrayVk::convertIndexBufferCPU(ContextVk *contextVk, angle::Result VertexArrayVk::convertIndexBufferCPU(ContextVk *contextVk,
gl::DrawElementsType indexType, gl::DrawElementsType indexType,
size_t indexCount, size_t indexCount,
......
...@@ -52,6 +52,13 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -52,6 +52,13 @@ class VertexArrayVk : public VertexArrayImpl
const void *indices, const void *indices,
uint32_t *indexCountOut); uint32_t *indexCountOut);
angle::Result handleLineLoopIndirect(ContextVk *contextVk,
BufferVk *indirectBufferVk,
gl::DrawElementsType glIndexType,
VkDeviceSize indirectBufferOffset,
vk::BufferHelper **indirectBufferOut,
VkDeviceSize *indirectBufferOffsetOut);
const gl::AttribArray<VkBuffer> &getCurrentArrayBufferHandles() const const gl::AttribArray<VkBuffer> &getCurrentArrayBufferHandles() const
{ {
return mCurrentArrayBufferHandles; return mCurrentArrayBufferHandles;
......
//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ConvertIndexIndirectLineloop.comp: Convert lineloop to linelist with primitive restart
// (if enabled). Will also output a new "command" buffer with adjusted index values.
//
// The following defines tweak the functionality, and a different shader is built based on these.
//
// - Flags:
// * Is32Bit: Process 32-bit indices, otherwise process 16-bit.
//
#version 450 core
layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
layout (set = 0, binding = 0) readonly buffer cmd
{
// Shader invocations read the cmd data to determine what indices to convert
// Command data at offset cmdOffset of buffer
uint cmdData[];
};
layout (set = 0, binding = 1) buffer dstCmd
{
// Shader outputs updated indirect buffer here.
uint dstCmdData[];
};
layout (set = 0, binding = 2) buffer dst
{
// Shader invocation outputs linelist(s) here.
uint dstData[];
};
layout (set = 0, binding = 3) readonly buffer src
{
// Source index buffer
uint srcData[];
};
layout (push_constant) uniform PushConstants
{
// Read offset in bytes into the cmdData array, divided by four.
uint cmdOffsetDiv4;
// Dst command offset in bytes into the cmdData array, divided by four.
uint dstCmdOffsetDiv4;
// Write offset in bytes into the dstData array, divided by four.
uint dstOffsetDiv4;
// Maximum size of the read buffer. The highest index value we will convert.
uint isRestartEnabled;
};
// Structure of command data loaded at offset cmdOffsetDiv4 of the cmdData buffer
// struct VkDrawIndexedIndirectCommand {
// uint32_t indexCount;
// uint32_t instanceCount;
// uint32_t firstIndex;
// int32_t vertexOffset;
// uint32_t firstInstance;
// };
uint GetIndexValue(uint index)
{
#ifdef Is32Bit
return srcData[index];
#else
// srcData points to 32bit words, get the word with our index value
uint srcBlock = srcData[index >> 1];
// Compute the shift necessary to access desired index value
uint srcShift = (index & 0x1) << 4;
// Only want 16bits
uint srcMask = 0xffff;
// unpacking correct 16bit index value from the 32bit word
uint value = (srcBlock >> srcShift) & srcMask;
return value;
#endif
}
void PutIndexValue(uint index, uint value)
{
#ifdef Is32Bit
dstData[dstOffsetDiv4 + index] = value;
return;
#else
// Compute index into dstData for our index value
uint dstIndex = dstOffsetDiv4 + (index >> 1);
// Get dest index value
uint srcBlock = dstData[dstIndex];
// Compute the shift for our index value
uint srcShift = (index & 0x1) << 4;
uint srcMask = 0xffff;
// Clear appropriate 16bits of 32bit word
srcBlock &= ~(srcMask << srcShift);
// Shift value to pack 16bit value into 32bit word
srcBlock |= value << srcShift;
// Store updated value in destination
dstData[dstIndex] = srcBlock;
#endif
}
void main()
{
// Load the relevant command info from cmdData
uint indexCount = cmdData[cmdOffsetDiv4];
uint firstIndex = cmdData[cmdOffsetDiv4 + 2];
uint endIndex = firstIndex + indexCount;
// Only first invocation does the work
if (gl_GlobalInvocationID.x >= 1)
return;
uint workingCount = 0;
uint srcIdx = firstIndex;
uint indicesRemaining = indexCount;
uint lineSize = 0;
uint firstIndexValue = 0;
while (indicesRemaining > 0)
{
uint indexValue;
#ifdef Is32Bit
uint restartValue = 0xffffffff;
#else
uint restartValue = 0xffff;
#endif
indexValue = GetIndexValue(srcIdx++);
if (lineSize == 0)
{
firstIndexValue = indexValue;
}
indicesRemaining--;
if ((isRestartEnabled == 1) && (indexValue == restartValue))
{
// We have a primitive restart, close the loop
if (lineSize > 1)
{
PutIndexValue(workingCount++, firstIndexValue);
}
if (lineSize > 0)
{
PutIndexValue(workingCount++, restartValue);
}
lineSize = 0;
} else {
PutIndexValue(workingCount, indexValue);
workingCount++;
lineSize++;
}
}
if (lineSize > 1)
{
PutIndexValue(workingCount, firstIndexValue);
workingCount++;
}
// Update new command buffer
dstCmdData[dstCmdOffsetDiv4] = workingCount;
dstCmdData[dstCmdOffsetDiv4 + 1] = cmdData[cmdOffsetDiv4 + 1];
dstCmdData[dstCmdOffsetDiv4 + 2] = 0;
dstCmdData[dstCmdOffsetDiv4 + 3] = cmdData[cmdOffsetDiv4 + 3];
dstCmdData[dstCmdOffsetDiv4 + 4] = cmdData[cmdOffsetDiv4 + 4];
}
{
"Description": [
"Copyright 2019 The ANGLE Project Authors. All rights reserved.",
"Use of this source code is governed by a BSD-style license that can be",
"found in the LICENSE file.",
"",
"ConvertIndexIndirectLineLoop.comp.json: Build parameters for ConvertIndexIndirectLineLoop.comp."
],
"Flags": [
"Is32Bit"
]
}
...@@ -34,10 +34,14 @@ constexpr VkClearColorValue kEmulatedInitColorValue = {{0, 0, 0, 1.0f}}; ...@@ -34,10 +34,14 @@ constexpr VkClearColorValue kEmulatedInitColorValue = {{0, 0, 0, 1.0f}};
// these values for emulated depth/stencil textures too. // these values for emulated depth/stencil textures too.
constexpr VkClearDepthStencilValue kWebGLInitDepthStencilValue = {1.0f, 0}; constexpr VkClearDepthStencilValue kWebGLInitDepthStencilValue = {1.0f, 0};
constexpr VkBufferUsageFlags kLineLoopDynamicBufferUsage = constexpr VkBufferUsageFlags kLineLoopDynamicBufferUsage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
constexpr int kLineLoopDynamicBufferInitialSize = 1024 * 1024; constexpr int kLineLoopDynamicBufferInitialSize = 1024 * 1024;
constexpr VkBufferUsageFlags kLineLoopDynamicIndirectBufferUsage =
VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
constexpr int kLineLoopDynamicIndirectBufferInitialSize = sizeof(VkDrawIndirectCommand) * 16;
// This is an arbitrary max. We can change this later if necessary. // This is an arbitrary max. We can change this later if necessary.
constexpr uint32_t kDefaultDescriptorPoolMaxSets = 128; constexpr uint32_t kDefaultDescriptorPoolMaxSets = 128;
...@@ -1067,6 +1071,8 @@ LineLoopHelper::LineLoopHelper(RendererVk *renderer) ...@@ -1067,6 +1071,8 @@ LineLoopHelper::LineLoopHelper(RendererVk *renderer)
// must be a multiple of the type indicated by indexType'. // must be a multiple of the type indicated by indexType'.
mDynamicIndexBuffer.init(renderer, kLineLoopDynamicBufferUsage, sizeof(uint32_t), mDynamicIndexBuffer.init(renderer, kLineLoopDynamicBufferUsage, sizeof(uint32_t),
kLineLoopDynamicBufferInitialSize, true); kLineLoopDynamicBufferInitialSize, true);
mDynamicIndirectBuffer.init(renderer, kLineLoopDynamicIndirectBufferUsage, sizeof(uint32_t),
kLineLoopDynamicIndirectBufferInitialSize, true);
} }
LineLoopHelper::~LineLoopHelper() = default; LineLoopHelper::~LineLoopHelper() = default;
...@@ -1210,14 +1216,73 @@ angle::Result LineLoopHelper::streamIndices(ContextVk *contextVk, ...@@ -1210,14 +1216,73 @@ angle::Result LineLoopHelper::streamIndices(ContextVk *contextVk,
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result LineLoopHelper::streamIndicesIndirect(ContextVk *contextVk,
gl::DrawElementsType glIndexType,
vk::BufferHelper *indexBuffer,
vk::BufferHelper *indirectBuffer,
VkDeviceSize indirectBufferOffset,
vk::BufferHelper **indexBufferOut,
VkDeviceSize *indexBufferOffsetOut,
vk::BufferHelper **indirectBufferOut,
VkDeviceSize *indirectBufferOffsetOut)
{
VkIndexType indexType = gl_vk::kIndexTypeMap[glIndexType];
auto unitSize = (indexType == VK_INDEX_TYPE_UINT16 ? sizeof(uint16_t) : sizeof(uint32_t));
size_t allocateBytes = static_cast<size_t>(indexBuffer->getSize() + unitSize);
if (contextVk->getState().isPrimitiveRestartEnabled())
{
// If primitive restart, new index buffer is 135% the size of the original index buffer. The
// smallest lineloop with primitive restart is 3 indices (point 1, point 2 and restart
// value) when converted to linelist becomes 4 vertices. Expansion of 4/3. Any larger
// lineloops would have less overhead and require less extra space. Any incomplete
// primitives can be dropped or left incomplete and thus not increase the size of the
// destination index buffer. Since we don't know the number of indices being used we'll use
// the size of the index buffer as allocated as the index count.
size_t numInputIndices = static_cast<size_t>(indexBuffer->getSize() / unitSize);
size_t numNewInputIndices = ((numInputIndices * 4) / 3) + 1;
allocateBytes = static_cast<size_t>(numNewInputIndices * unitSize);
}
mDynamicIndexBuffer.releaseInFlightBuffers(contextVk);
mDynamicIndirectBuffer.releaseInFlightBuffers(contextVk);
ANGLE_TRY(mDynamicIndexBuffer.allocate(contextVk, allocateBytes, nullptr, nullptr,
indexBufferOffsetOut, nullptr));
*indexBufferOut = mDynamicIndexBuffer.getCurrentBuffer();
ANGLE_TRY(mDynamicIndirectBuffer.allocate(contextVk, sizeof(VkDrawIndexedIndirectCommand),
nullptr, nullptr, indirectBufferOffsetOut, nullptr));
*indirectBufferOut = mDynamicIndirectBuffer.getCurrentBuffer();
vk::BufferHelper *destIndexBuffer = mDynamicIndexBuffer.getCurrentBuffer();
vk::BufferHelper *destIndirectBuffer = mDynamicIndirectBuffer.getCurrentBuffer();
// Copy relevant section of the source into destination at allocated offset. Note that the
// offset returned by allocate() above is in bytes. As is the indices offset pointer.
UtilsVk::ConvertLineLoopIndexIndirectParameters params = {};
params.indirectBufferOffset = static_cast<uint32_t>(indirectBufferOffset);
params.dstIndirectBufferOffset = static_cast<uint32_t>(*indirectBufferOffsetOut);
params.dstIndexBufferOffset = static_cast<uint32_t>(*indexBufferOffsetOut);
params.is32Bit = unitSize == 4;
ANGLE_TRY(contextVk->getUtils().convertLineLoopIndexIndirectBuffer(
contextVk, indirectBuffer, destIndirectBuffer, destIndexBuffer, indexBuffer, params));
return angle::Result::Continue;
}
void LineLoopHelper::release(ContextVk *contextVk) void LineLoopHelper::release(ContextVk *contextVk)
{ {
mDynamicIndexBuffer.release(contextVk->getRenderer()); mDynamicIndexBuffer.release(contextVk->getRenderer());
mDynamicIndirectBuffer.release(contextVk->getRenderer());
} }
void LineLoopHelper::destroy(VkDevice device) void LineLoopHelper::destroy(VkDevice device)
{ {
mDynamicIndexBuffer.destroy(device); mDynamicIndexBuffer.destroy(device);
mDynamicIndirectBuffer.destroy(device);
} }
// static // static
......
...@@ -422,6 +422,16 @@ class LineLoopHelper final : angle::NonCopyable ...@@ -422,6 +422,16 @@ class LineLoopHelper final : angle::NonCopyable
VkDeviceSize *bufferOffsetOut, VkDeviceSize *bufferOffsetOut,
uint32_t *indexCountOut); uint32_t *indexCountOut);
angle::Result streamIndicesIndirect(ContextVk *contextVk,
gl::DrawElementsType glIndexType,
vk::BufferHelper *indexBuffer,
vk::BufferHelper *indirectBuffer,
VkDeviceSize indirectBufferOffset,
vk::BufferHelper **indexBufferOut,
VkDeviceSize *indexBufferOffsetOut,
vk::BufferHelper **indirectBufferOut,
VkDeviceSize *indirectBufferOffsetOut);
void release(ContextVk *contextVk); void release(ContextVk *contextVk);
void destroy(VkDevice device); void destroy(VkDevice device);
...@@ -429,6 +439,7 @@ class LineLoopHelper final : angle::NonCopyable ...@@ -429,6 +439,7 @@ class LineLoopHelper final : angle::NonCopyable
private: private:
DynamicBuffer mDynamicIndexBuffer; DynamicBuffer mDynamicIndexBuffer;
DynamicBuffer mDynamicIndirectBuffer;
}; };
class FramebufferHelper; class FramebufferHelper;
......
...@@ -60,6 +60,8 @@ namespace ...@@ -60,6 +60,8 @@ namespace
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000001.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000001.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000002.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000002.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000003.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000003.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndexIndirectLineLoop.comp.00000000.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndexIndirectLineLoop.comp.00000001.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000000.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000000.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000001.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000001.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000002.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000002.inc"
...@@ -215,6 +217,12 @@ constexpr ShaderBlob kConvertIndex_comp_shaders[] = { ...@@ -215,6 +217,12 @@ constexpr ShaderBlob kConvertIndex_comp_shaders[] = {
{kConvertIndex_comp_00000002, sizeof(kConvertIndex_comp_00000002)}, {kConvertIndex_comp_00000002, sizeof(kConvertIndex_comp_00000002)},
{kConvertIndex_comp_00000003, sizeof(kConvertIndex_comp_00000003)}, {kConvertIndex_comp_00000003, sizeof(kConvertIndex_comp_00000003)},
}; };
constexpr ShaderBlob kConvertIndexIndirectLineLoop_comp_shaders[] = {
{kConvertIndexIndirectLineLoop_comp_00000000,
sizeof(kConvertIndexIndirectLineLoop_comp_00000000)},
{kConvertIndexIndirectLineLoop_comp_00000001,
sizeof(kConvertIndexIndirectLineLoop_comp_00000001)},
};
constexpr ShaderBlob kConvertVertex_comp_shaders[] = { constexpr ShaderBlob kConvertVertex_comp_shaders[] = {
{kConvertVertex_comp_00000000, sizeof(kConvertVertex_comp_00000000)}, {kConvertVertex_comp_00000000, sizeof(kConvertVertex_comp_00000000)},
{kConvertVertex_comp_00000001, sizeof(kConvertVertex_comp_00000001)}, {kConvertVertex_comp_00000001, sizeof(kConvertVertex_comp_00000001)},
...@@ -373,6 +381,10 @@ void ShaderLibrary::destroy(VkDevice device) ...@@ -373,6 +381,10 @@ void ShaderLibrary::destroy(VkDevice device)
{ {
shader.get().destroy(device); shader.get().destroy(device);
} }
for (RefCounted<ShaderAndSerial> &shader : mConvertIndexIndirectLineLoop_comp_shaders)
{
shader.get().destroy(device);
}
for (RefCounted<ShaderAndSerial> &shader : mConvertVertex_comp_shaders) for (RefCounted<ShaderAndSerial> &shader : mConvertVertex_comp_shaders)
{ {
shader.get().destroy(device); shader.get().destroy(device);
...@@ -433,6 +445,16 @@ angle::Result ShaderLibrary::getConvertIndex_comp(Context *context, ...@@ -433,6 +445,16 @@ angle::Result ShaderLibrary::getConvertIndex_comp(Context *context,
ArraySize(kConvertIndex_comp_shaders), shaderFlags, shaderOut); ArraySize(kConvertIndex_comp_shaders), shaderFlags, shaderOut);
} }
angle::Result ShaderLibrary::getConvertIndexIndirectLineLoop_comp(
Context *context,
uint32_t shaderFlags,
RefCounted<ShaderAndSerial> **shaderOut)
{
return GetShader(context, mConvertIndexIndirectLineLoop_comp_shaders,
kConvertIndexIndirectLineLoop_comp_shaders,
ArraySize(kConvertIndexIndirectLineLoop_comp_shaders), shaderFlags, shaderOut);
}
angle::Result ShaderLibrary::getConvertVertex_comp(Context *context, angle::Result ShaderLibrary::getConvertVertex_comp(Context *context,
uint32_t shaderFlags, uint32_t shaderFlags,
RefCounted<ShaderAndSerial> **shaderOut) RefCounted<ShaderAndSerial> **shaderOut)
......
...@@ -53,6 +53,8 @@ angle_vulkan_internal_shaders = [ ...@@ -53,6 +53,8 @@ angle_vulkan_internal_shaders = [
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000001.inc", "src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000001.inc",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000002.inc", "src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000002.inc",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000003.inc", "src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000003.inc",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndexIndirectLineLoop.comp.00000000.inc",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndexIndirectLineLoop.comp.00000001.inc",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000000.inc", "src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000000.inc",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000001.inc", "src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000001.inc",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000002.inc", "src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000002.inc",
......
...@@ -78,6 +78,15 @@ enum flags ...@@ -78,6 +78,15 @@ enum flags
constexpr size_t kArrayLen = 0x00000004; constexpr size_t kArrayLen = 0x00000004;
} // namespace ConvertIndex_comp } // namespace ConvertIndex_comp
namespace ConvertIndexIndirectLineLoop_comp
{
enum flags
{
kIs32Bit = 0x00000001,
};
constexpr size_t kArrayLen = 0x00000002;
} // namespace ConvertIndexIndirectLineLoop_comp
namespace ConvertVertex_comp namespace ConvertVertex_comp
{ {
enum flags enum flags
...@@ -208,6 +217,9 @@ class ShaderLibrary final : angle::NonCopyable ...@@ -208,6 +217,9 @@ class ShaderLibrary final : angle::NonCopyable
angle::Result getConvertIndex_comp(Context *context, angle::Result getConvertIndex_comp(Context *context,
uint32_t shaderFlags, uint32_t shaderFlags,
RefCounted<ShaderAndSerial> **shaderOut); RefCounted<ShaderAndSerial> **shaderOut);
angle::Result getConvertIndexIndirectLineLoop_comp(Context *context,
uint32_t shaderFlags,
RefCounted<ShaderAndSerial> **shaderOut);
angle::Result getConvertVertex_comp(Context *context, angle::Result getConvertVertex_comp(Context *context,
uint32_t shaderFlags, uint32_t shaderFlags,
RefCounted<ShaderAndSerial> **shaderOut); RefCounted<ShaderAndSerial> **shaderOut);
...@@ -236,6 +248,8 @@ class ShaderLibrary final : angle::NonCopyable ...@@ -236,6 +248,8 @@ class ShaderLibrary final : angle::NonCopyable
mBufferUtils_comp_shaders[InternalShader::BufferUtils_comp::kArrayLen]; mBufferUtils_comp_shaders[InternalShader::BufferUtils_comp::kArrayLen];
RefCounted<ShaderAndSerial> RefCounted<ShaderAndSerial>
mConvertIndex_comp_shaders[InternalShader::ConvertIndex_comp::kArrayLen]; mConvertIndex_comp_shaders[InternalShader::ConvertIndex_comp::kArrayLen];
RefCounted<ShaderAndSerial> mConvertIndexIndirectLineLoop_comp_shaders
[InternalShader::ConvertIndexIndirectLineLoop_comp::kArrayLen];
RefCounted<ShaderAndSerial> RefCounted<ShaderAndSerial>
mConvertVertex_comp_shaders[InternalShader::ConvertVertex_comp::kArrayLen]; mConvertVertex_comp_shaders[InternalShader::ConvertVertex_comp::kArrayLen];
RefCounted<ShaderAndSerial> RefCounted<ShaderAndSerial>
......
...@@ -625,7 +625,6 @@ ...@@ -625,7 +625,6 @@
// Indirect draw: // Indirect draw:
3564 VULKAN : dEQP-GLES31.functional.draw_indirect.draw_arrays_indirect.line_loop.* = SKIP 3564 VULKAN : dEQP-GLES31.functional.draw_indirect.draw_arrays_indirect.line_loop.* = SKIP
3564 VULKAN : dEQP-GLES31.functional.draw_indirect.draw_elements_indirect.line_loop.* = SKIP
3564 VULKAN : dEQP-GLES31.functional.draw_indirect.random.* = SKIP 3564 VULKAN : dEQP-GLES31.functional.draw_indirect.random.* = SKIP
// Tessellation geometry interaction: // Tessellation geometry interaction:
...@@ -655,4 +654,4 @@ ...@@ -655,4 +654,4 @@
3886 VULKAN : dEQP-GLES31.functional.image_load_store.3d.*layer = FAIL 3886 VULKAN : dEQP-GLES31.functional.image_load_store.3d.*layer = FAIL
// Inactive SSBOs with flexible array member (about 20% of these tests are affected): // Inactive SSBOs with flexible array member (about 20% of these tests are affected):
3714 VULKAN : dEQP-GLES31.functional.ssbo.layout.random.* = FAIL 3714 VULKAN : dEQP-GLES31.functional.ssbo.layout.random.* = FAIL
\ No newline at end of file
...@@ -43,6 +43,27 @@ class LineLoopTest : public ANGLETest ...@@ -43,6 +43,27 @@ class LineLoopTest : public ANGLETest
void testTearDown() override { glDeleteProgram(mProgram); } void testTearDown() override { glDeleteProgram(mProgram); }
void checkPixels()
{
std::vector<GLubyte> pixels(getWindowWidth() * getWindowHeight() * 4);
glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
&pixels[0]);
ASSERT_GL_NO_ERROR();
for (int y = 0; y < getWindowHeight(); y++)
{
for (int x = 0; x < getWindowWidth(); x++)
{
const GLubyte *pixel = &pixels[0] + ((y * getWindowWidth() + x) * 4);
EXPECT_EQ(pixel[0], 0);
EXPECT_EQ(pixel[1], pixel[2]);
ASSERT_EQ(pixel[3], 255);
}
}
}
void runTest(GLenum indexType, GLuint indexBuffer, const void *indexPtr) void runTest(GLenum indexType, GLuint indexBuffer, const void *indexPtr)
{ {
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
...@@ -67,23 +88,7 @@ class LineLoopTest : public ANGLETest ...@@ -67,23 +88,7 @@ class LineLoopTest : public ANGLETest
glUniform4f(mColorLocation, 0, 1, 0, 1); glUniform4f(mColorLocation, 0, 1, 0, 1);
glDrawElements(GL_LINE_STRIP, 5, GL_UNSIGNED_BYTE, stripIndices); glDrawElements(GL_LINE_STRIP, 5, GL_UNSIGNED_BYTE, stripIndices);
std::vector<GLubyte> pixels(getWindowWidth() * getWindowHeight() * 4); checkPixels();
glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
&pixels[0]);
ASSERT_GL_NO_ERROR();
for (int y = 0; y < getWindowHeight(); y++)
{
for (int x = 0; x < getWindowWidth(); x++)
{
const GLubyte *pixel = &pixels[0] + ((y * getWindowWidth() + x) * 4);
EXPECT_EQ(pixel[0], 0);
EXPECT_EQ(pixel[1], pixel[2]);
EXPECT_EQ(pixel[3], 255);
}
}
} }
GLuint mProgram; GLuint mProgram;
...@@ -197,6 +202,112 @@ TEST_P(LineLoopTest, DISABLED_DrawArraysWithLargeCount) ...@@ -197,6 +202,112 @@ TEST_P(LineLoopTest, DISABLED_DrawArraysWithLargeCount)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
class LineLoopIndirectTest : public LineLoopTest
{
protected:
void runTest(GLenum indexType, const void *indices, GLuint indicesSize, GLuint firstIndex)
{
struct DrawCommand
{
GLuint count;
GLuint primCount;
GLuint firstIndex;
GLint baseVertex;
GLuint reservedMustBeZero;
};
glClear(GL_COLOR_BUFFER_BIT);
static const GLfloat loopPositions[] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, -0.5f,
-0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f};
static const GLfloat stripPositions[] = {-0.5f, -0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f, -0.5f};
static const GLubyte stripIndices[] = {1, 0, 3, 2, 1};
glUseProgram(mProgram);
GLuint vertexArray = 0;
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
ASSERT_GL_NO_ERROR();
GLuint vertBuffer = 0;
glGenBuffers(1, &vertBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(loopPositions), loopPositions, GL_STATIC_DRAW);
glEnableVertexAttribArray(mPositionLocation);
glVertexAttribPointer(mPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
glUniform4f(mColorLocation, 0.0f, 0.0f, 1.0f, 1.0f);
ASSERT_GL_NO_ERROR();
GLuint buf;
glGenBuffers(1, &buf);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesSize, indices, GL_STATIC_DRAW);
DrawCommand cmdBuffer = {};
cmdBuffer.count = 4;
cmdBuffer.firstIndex = firstIndex;
cmdBuffer.primCount = 1;
GLuint indirectBuf = 0;
glGenBuffers(1, &indirectBuf);
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuf);
glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawCommand), &cmdBuffer, GL_STATIC_DRAW);
ASSERT_GL_NO_ERROR();
glDrawElementsIndirect(GL_LINE_LOOP, indexType, nullptr);
ASSERT_GL_NO_ERROR();
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
glDeleteBuffers(1, &indirectBuf);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &buf);
glBindVertexArray(0);
glDeleteVertexArrays(1, &vertexArray);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &vertBuffer);
glEnableVertexAttribArray(mPositionLocation);
glVertexAttribPointer(mPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, stripPositions);
glUniform4f(mColorLocation, 0, 1, 0, 1);
glDrawElements(GL_LINE_STRIP, 5, GL_UNSIGNED_BYTE, stripIndices);
checkPixels();
}
};
TEST_P(LineLoopIndirectTest, UByteIndexIndirectBuffer)
{
// Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
ignoreD3D11SDKLayersWarnings();
static const GLubyte indices[] = {0, 7, 6, 9, 8, 0};
// Start at index 1.
runTest(GL_UNSIGNED_BYTE, reinterpret_cast<const void *>(indices), sizeof(indices), 1);
}
TEST_P(LineLoopIndirectTest, UShortIndexIndirectBuffer)
{
// Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
ignoreD3D11SDKLayersWarnings();
static const GLushort indices[] = {0, 7, 6, 9, 8, 0};
// Start at index 1.
runTest(GL_UNSIGNED_SHORT, reinterpret_cast<const void *>(indices), sizeof(indices), 1);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these // Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against. // tests should be run against.
ANGLE_INSTANTIATE_TEST(LineLoopTest, ANGLE_INSTANTIATE_TEST(LineLoopTest,
...@@ -205,3 +316,5 @@ ANGLE_INSTANTIATE_TEST(LineLoopTest, ...@@ -205,3 +316,5 @@ ANGLE_INSTANTIATE_TEST(LineLoopTest,
ES2_OPENGL(), ES2_OPENGL(),
ES2_OPENGLES(), ES2_OPENGLES(),
ES2_VULKAN()); ES2_VULKAN());
ANGLE_INSTANTIATE_TEST(LineLoopIndirectTest, ES31_OPENGLES(), ES31_VULKAN());
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