Commit fbe49a8f by Qin Jiajia Committed by Commit Bot

ES31: Implement DrawArraysIndirect D3D part

There are four buffer types for vertex attribute storage in D3D11: DIRECT STATIC DYNAMIC CURRENT_VALUE When drawing, it will call applyVertexBuffer to bind the right type buffers in D3D11. DIRECT uses the gl buffer directly without any translation. CURRENT_VALUE uses a single value for the attribute. STATIC translates the whole vertex buffer once. So it doesn't need the first, count and instance informations since it always translates the whole buffer. DYNAMIC translates the data every frame. To improve the performance, in implementation, it only translates 'count' vertexes from 'first' location in vertex buffer with one drawing for non-instanced vertices. 'first' and 'count' are got from draw parameter list. And for the translated vertex buffer, when drawing, the first vertex location is 0. From above analysis, we can see that if all attribute storages are non-dynamic, we can directly use the indirect buffer to draw. But for dynamic storages, we have to calculate the first, count, and instances from indirect buffer and apply them to translate the dynamic type buffers. Meanwhile, we have to set the first to 0 (see above description)when drawing. DrawArrysIndirect implementation is like below: 1. Check whether all vertex attributes are non-dynamic 2. If yes, applyVertexBuffer and DrawInstancedIndirect 3. If no, 1) calculate first, count, and instances from indirect buffer. 2) applyVertexBuffer with these parameters. 4) Use DrawInstanced instead of DrawInstancedIndirect. BUG=angleproject:1595 TEST=dEQP-GLES31.functional.draw_indirect.draw_arrays_indirect* Change-Id: I36431f416443279d51de523b07ce60727914cbbf Reviewed-on: https://chromium-review.googlesource.com/446690 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent fe34780f
...@@ -168,6 +168,27 @@ struct DepthStencilState ...@@ -168,6 +168,27 @@ struct DepthStencilState
GLuint stencilBackWritemask; GLuint stencilBackWritemask;
}; };
struct DrawArraysIndirectCommand
{
GLuint count;
GLuint instanceCount;
GLuint first;
GLuint baseInstance;
};
static_assert(sizeof(DrawArraysIndirectCommand) == 16,
"Unexpected size of DrawArraysIndirectCommand");
struct DrawElementsIndirectCommand
{
GLuint count;
GLuint primCount;
GLuint firstIndex;
GLint baseVertex;
GLuint baseInstance;
};
static_assert(sizeof(DrawElementsIndirectCommand) == 20,
"Unexpected size of DrawElementsIndirectCommand");
// State from Table 6.10 (state per sampler object) // State from Table 6.10 (state per sampler object)
struct SamplerState struct SamplerState
{ {
......
...@@ -1110,6 +1110,13 @@ void Buffer11::NativeStorage::FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, ...@@ -1110,6 +1110,13 @@ void Buffer11::NativeStorage::FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
bufferDesc->CPUAccessFlags = 0; bufferDesc->CPUAccessFlags = 0;
break; break;
case BUFFER_USAGE_INDIRECT:
bufferDesc->MiscFlags = D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
bufferDesc->Usage = D3D11_USAGE_DEFAULT;
bufferDesc->BindFlags = 0;
bufferDesc->CPUAccessFlags = 0;
break;
case BUFFER_USAGE_PIXEL_UNPACK: case BUFFER_USAGE_PIXEL_UNPACK:
bufferDesc->Usage = D3D11_USAGE_DEFAULT; bufferDesc->Usage = D3D11_USAGE_DEFAULT;
bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE; bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE;
......
...@@ -35,6 +35,8 @@ enum BufferUsage ...@@ -35,6 +35,8 @@ enum BufferUsage
BUFFER_USAGE_STAGING, BUFFER_USAGE_STAGING,
BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK,
BUFFER_USAGE_INDEX, BUFFER_USAGE_INDEX,
// TODO: possibly share this buffer type with shader storage buffers.
BUFFER_USAGE_INDIRECT,
BUFFER_USAGE_PIXEL_UNPACK, BUFFER_USAGE_PIXEL_UNPACK,
BUFFER_USAGE_PIXEL_PACK, BUFFER_USAGE_PIXEL_PACK,
BUFFER_USAGE_UNIFORM, BUFFER_USAGE_UNIFORM,
......
...@@ -194,14 +194,12 @@ gl::Error Context11::drawRangeElements(GLenum mode, ...@@ -194,14 +194,12 @@ gl::Error Context11::drawRangeElements(GLenum mode,
gl::Error Context11::drawArraysIndirect(GLenum mode, const GLvoid *indirect) gl::Error Context11::drawArraysIndirect(GLenum mode, const GLvoid *indirect)
{ {
UNIMPLEMENTED(); return mRenderer->genericDrawIndirect(this, mode, GL_NONE, indirect);
return gl::InternalError() << "DrawArraysIndirect hasn't been implemented for D3D11 backend.";
} }
gl::Error Context11::drawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect) gl::Error Context11::drawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect)
{ {
UNIMPLEMENTED(); return mRenderer->genericDrawIndirect(this, mode, type, indirect);
return gl::InternalError() << "DrawElementsIndirect hasn't been implemented for D3D11 backend.";
} }
GLenum Context11::getResetStatus() GLenum Context11::getResetStatus()
......
...@@ -2013,6 +2013,67 @@ gl::Error Renderer11::drawElementsImpl(const gl::ContextState &data, ...@@ -2013,6 +2013,67 @@ gl::Error Renderer11::drawElementsImpl(const gl::ContextState &data,
return gl::NoError(); return gl::NoError();
} }
gl::Error Renderer11::drawArraysIndirectImpl(const gl::ContextState &data,
GLenum mode,
const GLvoid *indirect)
{
if (skipDraw(data, mode))
{
return gl::NoError();
}
const auto &glState = data.getState();
gl::Buffer *drawIndirectBuffer = glState.getDrawIndirectBuffer();
ASSERT(drawIndirectBuffer);
Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
uintptr_t offset = reinterpret_cast<uintptr_t>(indirect);
const auto &vertexArray = glState.getVertexArray();
auto *vertexArray11 = GetImplAs<VertexArray11>(vertexArray);
// If there is no dynamic attribute, we can directly use the indirect buffer.
if (!vertexArray11->hasDynamicAttrib(glState) && mode != GL_LINE_LOOP &&
mode != GL_TRIANGLE_FAN)
{
applyVertexBuffer(glState, mode, 0, 0, 0, nullptr);
ID3D11Buffer *buffer = nullptr;
ANGLE_TRY_RESULT(storage->getBuffer(BUFFER_USAGE_INDIRECT), buffer);
mDeviceContext->DrawInstancedIndirect(buffer, static_cast<unsigned int>(offset));
return gl::NoError();
}
const uint8_t *bufferData = nullptr;
ANGLE_TRY(storage->getData(&bufferData));
ASSERT(bufferData);
const gl::DrawArraysIndirectCommand *args =
reinterpret_cast<const gl::DrawArraysIndirectCommand *>(bufferData + offset);
GLuint count = args->count;
GLuint instances = args->instanceCount;
GLuint first = args->first;
ANGLE_TRY(applyVertexBuffer(glState, mode, first, count, instances, nullptr));
if (mode == GL_LINE_LOOP)
{
return drawLineLoop(data, count, GL_NONE, nullptr, 0, instances);
}
if (mode == GL_TRIANGLE_FAN)
{
return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances);
}
mDeviceContext->DrawInstanced(count, instances, 0, 0);
return gl::NoError();
}
gl::Error Renderer11::drawElementsIndirectImpl(const gl::ContextState &data,
GLenum mode,
GLenum type,
const GLvoid *indirect)
{
UNIMPLEMENTED();
return gl::InternalError() << "DrawElementsIndirect hasn't been implemented for D3D11 backend.";
}
gl::Error Renderer11::drawLineLoop(const gl::ContextState &data, gl::Error Renderer11::drawLineLoop(const gl::ContextState &data,
GLsizei count, GLsizei count,
GLenum type, GLenum type,
...@@ -4583,6 +4644,40 @@ gl::Error Renderer11::genericDrawArrays(Context11 *context, ...@@ -4583,6 +4644,40 @@ gl::Error Renderer11::genericDrawArrays(Context11 *context,
return gl::NoError(); return gl::NoError();
} }
gl::Error Renderer11::genericDrawIndirect(Context11 *context,
GLenum mode,
GLenum type,
const GLvoid *indirect)
{
const auto &data = context->getContextState();
const auto &glState = data.getState();
gl::Program *program = glState.getProgram();
ASSERT(program != nullptr);
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
bool usesPointSize = programD3D->usesPointSize();
programD3D->updateSamplerMapping();
ANGLE_TRY(generateSwizzles(data));
applyPrimitiveType(mode, 0, usesPointSize);
ANGLE_TRY(updateState(data, mode));
ANGLE_TRY(applyTransformFeedbackBuffers(data));
ASSERT(!glState.isTransformFeedbackActiveUnpaused());
ANGLE_TRY(applyTextures(context, data));
ANGLE_TRY(applyShaders(data, mode));
ANGLE_TRY(programD3D->applyUniformBuffers(data));
if (type == GL_NONE)
{
ANGLE_TRY(drawArraysIndirectImpl(data, mode, indirect));
}
else
{
ANGLE_TRY(drawElementsIndirectImpl(data, mode, type, indirect));
}
return gl::NoError();
}
FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::FramebufferState &state) FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::FramebufferState &state)
{ {
return new Framebuffer11(state, this); return new Framebuffer11(state, this);
......
...@@ -374,6 +374,11 @@ class Renderer11 : public RendererD3D ...@@ -374,6 +374,11 @@ class Renderer11 : public RendererD3D
GLsizei instances, GLsizei instances,
const gl::IndexRange &indexRange); const gl::IndexRange &indexRange);
gl::Error genericDrawIndirect(Context11 *context,
GLenum mode,
GLenum type,
const GLvoid *indirect);
// Necessary hack for default framebuffers in D3D. // Necessary hack for default framebuffers in D3D.
FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override; FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
...@@ -397,6 +402,13 @@ class Renderer11 : public RendererD3D ...@@ -397,6 +402,13 @@ class Renderer11 : public RendererD3D
GLenum type, GLenum type,
const GLvoid *indices, const GLvoid *indices,
GLsizei instances); GLsizei instances);
gl::Error drawArraysIndirectImpl(const gl::ContextState &data,
GLenum mode,
const GLvoid *indirect);
gl::Error drawElementsIndirectImpl(const gl::ContextState &data,
GLenum mode,
GLenum type,
const GLvoid *indirect);
void generateCaps(gl::Caps *outCaps, void generateCaps(gl::Caps *outCaps,
gl::TextureCapsMap *outTextureCaps, gl::TextureCapsMap *outTextureCaps,
......
...@@ -54,6 +54,24 @@ void VertexArray11::syncState(const gl::VertexArray::DirtyBits &dirtyBits) ...@@ -54,6 +54,24 @@ void VertexArray11::syncState(const gl::VertexArray::DirtyBits &dirtyBits)
} }
} }
void VertexArray11::flushAttribUpdates(const gl::State &state)
{
const gl::Program *program = state.getProgram();
const auto &activeLocations = program->getActiveAttribLocationsMask();
if (mAttribsToUpdate.any())
{
// Skip attrib locations the program doesn't use.
const auto &activeToUpdate = (mAttribsToUpdate & activeLocations);
for (auto toUpdateIndex : angle::IterateBitSet(activeToUpdate))
{
mAttribsToUpdate.reset(toUpdateIndex);
updateVertexAttribStorage(toUpdateIndex);
}
}
}
void VertexArray11::updateVertexAttribStorage(size_t attribIndex) void VertexArray11::updateVertexAttribStorage(size_t attribIndex)
{ {
const auto &attrib = mData.getVertexAttribute(attribIndex); const auto &attrib = mData.getVertexAttribute(attribIndex);
...@@ -115,29 +133,24 @@ void VertexArray11::updateVertexAttribStorage(size_t attribIndex) ...@@ -115,29 +133,24 @@ void VertexArray11::updateVertexAttribStorage(size_t attribIndex)
} }
} }
bool VertexArray11::hasDynamicAttrib(const gl::State &state)
{
flushAttribUpdates(state);
return mDynamicAttribsMask.any();
}
gl::Error VertexArray11::updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager, gl::Error VertexArray11::updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager,
const gl::State &state, const gl::State &state,
GLint start, GLint start,
GLsizei count, GLsizei count,
GLsizei instances) GLsizei instances)
{ {
flushAttribUpdates(state);
const gl::Program *program = state.getProgram(); const gl::Program *program = state.getProgram();
const auto &activeLocations = program->getActiveAttribLocationsMask(); const auto &activeLocations = program->getActiveAttribLocationsMask();
const auto &attribs = mData.getVertexAttributes();
if (mAttribsToUpdate.any()) const auto &bindings = mData.getVertexBindings();
{
// Skip attrib locations the program doesn't use.
const auto &activeToUpdate = (mAttribsToUpdate & activeLocations);
for (auto toUpdateIndex : angle::IterateBitSet(activeToUpdate))
{
mAttribsToUpdate.reset(toUpdateIndex);
updateVertexAttribStorage(toUpdateIndex);
}
}
const auto &attribs = mData.getVertexAttributes();
const auto &bindings = mData.getVertexBindings();
if (mAttribsToTranslate.any()) if (mAttribsToTranslate.any())
{ {
...@@ -153,8 +166,8 @@ gl::Error VertexArray11::updateDirtyAndDynamicAttribs(VertexDataManager *vertexD ...@@ -153,8 +166,8 @@ gl::Error VertexArray11::updateDirtyAndDynamicAttribs(VertexDataManager *vertexD
state.getVertexAttribCurrentValue(static_cast<unsigned int>(dirtyAttribIndex)); state.getVertexAttribCurrentValue(static_cast<unsigned int>(dirtyAttribIndex));
// Record basic attrib info // Record basic attrib info
translatedAttrib->attribute = &attribs[dirtyAttribIndex]; translatedAttrib->attribute = &attribs[dirtyAttribIndex];
translatedAttrib->binding = &bindings[translatedAttrib->attribute->bindingIndex]; translatedAttrib->binding = &bindings[translatedAttrib->attribute->bindingIndex];
translatedAttrib->currentValueType = currentValue.Type; translatedAttrib->currentValueType = currentValue.Type;
translatedAttrib->divisor = translatedAttrib->binding->divisor; translatedAttrib->divisor = translatedAttrib->binding->divisor;
......
...@@ -24,6 +24,8 @@ class VertexArray11 : public VertexArrayImpl, public angle::SignalReceiver ...@@ -24,6 +24,8 @@ class VertexArray11 : public VertexArrayImpl, public angle::SignalReceiver
~VertexArray11() override; ~VertexArray11() override;
void syncState(const gl::VertexArray::DirtyBits &dirtyBits) override; void syncState(const gl::VertexArray::DirtyBits &dirtyBits) override;
// This will flush any pending attrib updates and then check the dynamic attribs mask.
bool hasDynamicAttrib(const gl::State &state);
gl::Error updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager, gl::Error updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager,
const gl::State &state, const gl::State &state,
GLint start, GLint start,
...@@ -38,6 +40,7 @@ class VertexArray11 : public VertexArrayImpl, public angle::SignalReceiver ...@@ -38,6 +40,7 @@ class VertexArray11 : public VertexArrayImpl, public angle::SignalReceiver
private: private:
void updateVertexAttribStorage(size_t attribIndex); void updateVertexAttribStorage(size_t attribIndex);
void flushAttribUpdates(const gl::State &state);
std::vector<VertexStorageType> mAttributeStorageTypes; std::vector<VertexStorageType> mAttributeStorageTypes;
std::vector<TranslatedAttribute> mTranslatedAttribs; std::vector<TranslatedAttribute> mTranslatedAttribs;
......
...@@ -104,7 +104,9 @@ ...@@ -104,7 +104,9 @@
1442 OPENGL : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.samples_4_texture_uint_2d_array = FAIL 1442 OPENGL : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.samples_4_texture_uint_2d_array = FAIL
// D3D11 Failing Tests // D3D11 Failing Tests
1442 D3D11 : dEQP-GLES31.functional.draw_indirect.* = FAIL 1595 D3D11 : dEQP-GLES31.functional.draw_indirect.draw_elements_indirect.* = FAIL
1595 D3D11 : dEQP-GLES31.functional.draw_indirect.instancing.* = FAIL
1595 D3D11 : dEQP-GLES31.functional.draw_indirect.random.* = FAIL
1442 D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.* = FAIL 1442 D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.* = FAIL
1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_color_texture_samples_* = FAIL 1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_color_texture_samples_* = FAIL
1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_depth_texture_samples_* = FAIL 1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_depth_texture_samples_* = FAIL
...@@ -167,10 +169,10 @@ ...@@ -167,10 +169,10 @@
1442 D3D11 : dEQP-GLES31.functional.debug.error_groups.case_10 = SKIP 1442 D3D11 : dEQP-GLES31.functional.debug.error_groups.case_10 = SKIP
// OPENGL Failing Tests // OPENGL Failing Tests
1663 OPENGL : dEQP-GLES31.functional.draw_indirect.compute_interop.* = FAIL
1665 WIN NVIDIA OPENGL : dEQP-GLES31.functional.draw_indirect.negative.command_offset_not_in_buffer_unsigned32_wrap = FAIL 1665 WIN NVIDIA OPENGL : dEQP-GLES31.functional.draw_indirect.negative.command_offset_not_in_buffer_unsigned32_wrap = FAIL
// OpenGL and D3D11 Failing Tests // OpenGL and D3D11 Failing Tests
1663 OPENGL D3D11 : dEQP-GLES31.functional.draw_indirect.compute_interop.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_var.compute.num_work_groups = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_var.compute.num_work_groups = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_var.compute.work_group_size = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_var.compute.work_group_size = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_var.compute.work_group_id = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_var.compute.work_group_id = FAIL
......
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