Commit df68a6f0 by Jamie Madill Committed by Commit Bot

Vulkan: Implement a simple graphics pipeline.

BUG=angleproject:1580 Change-Id: Iceaed896db22dc9eefa3f1bee7d6142fcfb20368 Reviewed-on: https://chromium-review.googlesource.com/412267 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent b3280707
......@@ -403,6 +403,7 @@ class Program final : angle::NonCopyable, public LabeledObject
{
return mState.mSamplerBindings;
}
const ProgramState &getState() const { return mState; }
private:
class Bindings final : angle::NonCopyable
......
......@@ -125,6 +125,6 @@ class VertexArray final : public LabeledObject
rx::VertexArrayImpl *mVertexArray;
};
}
} // namespace gl
#endif // LIBANGLE_VERTEXARRAY_H_
......@@ -163,4 +163,9 @@ vk::Error BufferVk::setDataImpl(const uint8_t *data, size_t size, size_t offset)
return vk::NoError();
}
const vk::Buffer &BufferVk::getVkBuffer() const
{
return mBuffer;
}
} // namespace rx
......@@ -46,6 +46,8 @@ class BufferVk : public BufferImpl
bool primitiveRestartEnabled,
gl::IndexRange *outRange) override;
const vk::Buffer &getVkBuffer() const;
private:
vk::Error setDataImpl(const uint8_t *data, size_t size, size_t offset);
......
......@@ -9,7 +9,9 @@
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "common/BitSetIterator.h"
#include "common/debug.h"
#include "libANGLE/Program.h"
#include "libANGLE/renderer/vulkan/BufferVk.h"
#include "libANGLE/renderer/vulkan/CompilerVk.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
......@@ -27,6 +29,7 @@
#include "libANGLE/renderer/vulkan/TextureVk.h"
#include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
#include "libANGLE/renderer/vulkan/VertexArrayVk.h"
#include "libANGLE/renderer/vulkan/formatutilsvk.h"
namespace rx
{
......@@ -59,8 +62,220 @@ gl::Error ContextVk::finish()
gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count)
{
UNIMPLEMENTED();
return gl::Error(GL_INVALID_OPERATION);
VkDevice device = mRenderer->getDevice();
const auto &state = mState.getState();
const auto &programGL = state.getProgram();
const auto &vao = state.getVertexArray();
const auto &attribs = vao->getVertexAttributes();
const auto &programVk = GetImplAs<ProgramVk>(programGL);
const auto *drawFBO = state.getDrawFramebuffer();
FramebufferVk *vkFBO = GetImplAs<FramebufferVk>(drawFBO);
// { vertex, fragment }
VkPipelineShaderStageCreateInfo shaderStages[2];
shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[0].pNext = nullptr;
shaderStages[0].flags = 0;
shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
shaderStages[0].module = programVk->getLinkedVertexModule().getHandle();
shaderStages[0].pName = "main";
shaderStages[0].pSpecializationInfo = nullptr;
shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[1].pNext = nullptr;
shaderStages[1].flags = 0;
shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
shaderStages[1].module = programVk->getLinkedFragmentModule().getHandle();
shaderStages[1].pName = "main";
shaderStages[1].pSpecializationInfo = nullptr;
// Process vertex attributes
// TODO(jmadill): Caching with dirty bits.
std::vector<VkVertexInputBindingDescription> vertexBindings;
std::vector<VkVertexInputAttributeDescription> vertexAttribs;
std::vector<VkBuffer> vertexHandles;
std::vector<VkDeviceSize> vertexOffsets;
for (auto attribIndex : angle::IterateBitSet(programGL->getActiveAttribLocationsMask()))
{
const auto &attrib = attribs[attribIndex];
if (attrib.enabled)
{
VkVertexInputBindingDescription bindingDesc;
bindingDesc.binding = static_cast<uint32_t>(vertexBindings.size());
bindingDesc.stride = static_cast<uint32_t>(gl::ComputeVertexAttributeTypeSize(attrib));
bindingDesc.inputRate =
(attrib.divisor > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
VkVertexInputAttributeDescription attribDesc;
attribDesc.binding = bindingDesc.binding;
attribDesc.format = vk::GetNativeVertexFormat(vertexFormatType);
attribDesc.location = static_cast<uint32_t>(attribIndex);
attribDesc.offset = static_cast<uint32_t>(attrib.offset);
vertexBindings.push_back(bindingDesc);
vertexAttribs.push_back(attribDesc);
// TODO(jmadill): Offset handling.
gl::Buffer *bufferGL = attrib.buffer.get();
ASSERT(bufferGL);
BufferVk *bufferVk = GetImplAs<BufferVk>(bufferGL);
vertexHandles.push_back(bufferVk->getVkBuffer().getHandle());
vertexOffsets.push_back(0);
}
else
{
UNIMPLEMENTED();
}
}
// TODO(jmadill): Validate with ASSERT against physical device limits/caps?
VkPipelineVertexInputStateCreateInfo vertexInputState;
vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputState.pNext = nullptr;
vertexInputState.flags = 0;
vertexInputState.vertexBindingDescriptionCount = static_cast<uint32_t>(vertexBindings.size());
vertexInputState.pVertexBindingDescriptions = vertexBindings.data();
vertexInputState.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertexAttribs.size());
vertexInputState.pVertexAttributeDescriptions = vertexAttribs.data();
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState;
inputAssemblyState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssemblyState.pNext = nullptr;
inputAssemblyState.flags = 0;
inputAssemblyState.topology = gl_vk::GetPrimitiveTopology(mode);
inputAssemblyState.primitiveRestartEnable = VK_FALSE;
const gl::Rectangle &viewportGL = state.getViewport();
VkViewport viewportVk;
viewportVk.x = static_cast<float>(viewportGL.x);
viewportVk.y = static_cast<float>(viewportGL.y);
viewportVk.width = static_cast<float>(viewportGL.width);
viewportVk.height = static_cast<float>(viewportGL.height);
viewportVk.minDepth = state.getNearPlane();
viewportVk.maxDepth = state.getFarPlane();
// TODO(jmadill): Scissor.
VkRect2D scissorVk;
scissorVk.offset.x = viewportGL.x;
scissorVk.offset.y = viewportGL.y;
scissorVk.extent.width = viewportGL.width;
scissorVk.extent.height = viewportGL.height;
VkPipelineViewportStateCreateInfo viewportState;
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.pNext = nullptr;
viewportState.flags = 0;
viewportState.viewportCount = 1;
viewportState.pViewports = &viewportVk;
viewportState.scissorCount = 1;
viewportState.pScissors = &scissorVk;
// TODO(jmadill): Extra rasterizer state features.
VkPipelineRasterizationStateCreateInfo rasterState;
rasterState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterState.pNext = nullptr;
rasterState.flags = 0;
rasterState.depthClampEnable = VK_FALSE;
rasterState.rasterizerDiscardEnable = VK_FALSE;
rasterState.polygonMode = VK_POLYGON_MODE_FILL;
rasterState.cullMode = gl_vk::GetCullMode(state.getRasterizerState());
rasterState.frontFace = gl_vk::GetFrontFace(state.getRasterizerState().frontFace);
rasterState.depthBiasEnable = VK_FALSE;
rasterState.depthBiasConstantFactor = 0.0f;
rasterState.depthBiasClamp = 0.0f;
rasterState.depthBiasSlopeFactor = 0.0f;
rasterState.lineWidth = state.getLineWidth();
// TODO(jmadill): Multisample state.
VkPipelineMultisampleStateCreateInfo multisampleState;
multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampleState.pNext = nullptr;
multisampleState.flags = 0;
multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
multisampleState.sampleShadingEnable = VK_FALSE;
multisampleState.minSampleShading = 0.0f;
multisampleState.pSampleMask = nullptr;
multisampleState.alphaToCoverageEnable = VK_FALSE;
multisampleState.alphaToOneEnable = VK_FALSE;
// TODO(jmadill): Depth/stencil state.
// TODO(jmadill): Blend state/MRT.
VkPipelineColorBlendAttachmentState blendAttachmentState;
blendAttachmentState.blendEnable = VK_FALSE;
blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
blendAttachmentState.colorWriteMask = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
VkPipelineColorBlendStateCreateInfo blendState;
blendState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
blendState.pNext = 0;
blendState.flags = 0;
blendState.logicOpEnable = VK_FALSE;
blendState.logicOp = VK_LOGIC_OP_CLEAR;
blendState.attachmentCount = 1;
blendState.pAttachments = &blendAttachmentState;
blendState.blendConstants[0] = 0.0f;
blendState.blendConstants[1] = 0.0f;
blendState.blendConstants[2] = 0.0f;
blendState.blendConstants[3] = 0.0f;
// TODO(jmadill): Dynamic state.
vk::RenderPass *renderPass = nullptr;
ANGLE_TRY_RESULT(vkFBO->getRenderPass(device), renderPass);
ASSERT(renderPass && renderPass->valid());
vk::PipelineLayout *pipelineLayout = nullptr;
ANGLE_TRY_RESULT(programVk->getPipelineLayout(device), pipelineLayout);
ASSERT(pipelineLayout && pipelineLayout->valid());
VkGraphicsPipelineCreateInfo pipelineInfo;
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.pNext = nullptr;
pipelineInfo.flags = 0;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;
pipelineInfo.pVertexInputState = &vertexInputState;
pipelineInfo.pInputAssemblyState = &inputAssemblyState;
pipelineInfo.pTessellationState = nullptr;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterState;
pipelineInfo.pMultisampleState = &multisampleState;
pipelineInfo.pDepthStencilState = nullptr;
pipelineInfo.pColorBlendState = &blendState;
pipelineInfo.pDynamicState = nullptr;
pipelineInfo.layout = pipelineLayout->getHandle();
pipelineInfo.renderPass = renderPass->getHandle();
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
pipelineInfo.basePipelineIndex = 0;
vk::Pipeline newPipeline(device);
ANGLE_TRY(newPipeline.initGraphics(pipelineInfo));
mCurrentPipeline = std::move(newPipeline);
vk::CommandBuffer *commandBuffer = mRenderer->getCommandBuffer();
ANGLE_TRY(vkFBO->beginRenderPass(device, commandBuffer, state));
commandBuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mCurrentPipeline);
commandBuffer->bindVertexBuffers(0, vertexHandles, vertexOffsets);
commandBuffer->draw(count, 1, first, 0);
commandBuffer->endRenderPass();
ANGLE_TRY(commandBuffer->end());
ANGLE_TRY(mRenderer->submitAndFinishCommandBuffer(*commandBuffer));
return gl::NoError();
}
gl::Error ContextVk::drawArraysInstanced(GLenum mode,
......
......@@ -130,6 +130,7 @@ class ContextVk : public ContextImpl
private:
RendererVk *mRenderer;
vk::Pipeline mCurrentPipeline;
};
} // namespace rx
......
......@@ -363,10 +363,12 @@ gl::ErrorOrResult<vk::RenderPass *> FramebufferVk::getRenderPass(VkDevice device
colorDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorDesc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
// We might want to transition directly to PRESENT_SRC for Surface attachments.
colorDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
colorRef.attachment = static_cast<uint32_t>(colorAttachments.size()) - 1u;
colorRef.layout = VK_IMAGE_LAYOUT_GENERAL;
colorRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachmentDescs.push_back(colorDesc);
colorAttachmentRefs.push_back(colorRef);
......@@ -497,7 +499,7 @@ gl::ErrorOrResult<vk::Framebuffer *> FramebufferVk::getFramebuffer(VkDevice devi
framebufferInfo.layers = 1;
vk::Framebuffer framebuffer(device);
ANGLE_TRY(framebuffer.init(framebufferInfo));
ANGLE_TRY(static_cast<gl::Error>(framebuffer.init(framebufferInfo)));
mFramebuffer = std::move(framebuffer);
......@@ -510,4 +512,41 @@ gl::Error FramebufferVk::getSamplePosition(size_t index, GLfloat *xy) const
return gl::InternalError() << "getSamplePosition is unimplemented.";
}
gl::Error FramebufferVk::beginRenderPass(VkDevice device,
vk::CommandBuffer *commandBuffer,
const gl::State &glState)
{
vk::Framebuffer *framebuffer = nullptr;
ANGLE_TRY_RESULT(getFramebuffer(device), framebuffer);
ASSERT(framebuffer && framebuffer->valid());
vk::RenderPass *renderPass = nullptr;
ANGLE_TRY_RESULT(getRenderPass(device), renderPass);
ASSERT(renderPass && renderPass->valid());
// TODO(jmadill): Proper clear value implementation.
VkClearColorValue colorClear;
memset(&colorClear, 0, sizeof(VkClearColorValue));
colorClear.float32[0] = glState.getColorClearValue().red;
colorClear.float32[1] = glState.getColorClearValue().green;
colorClear.float32[2] = glState.getColorClearValue().blue;
colorClear.float32[3] = glState.getColorClearValue().alpha;
std::vector<VkClearValue> attachmentClearValues;
attachmentClearValues.push_back({colorClear});
// Updated the cached image layout of the attachments in this FBO.
// For a default FBO, we need to call through to the WindowSurfaceVk
// TODO(jmadill): Iterate over all attachments.
ASSERT(mBackbuffer);
RenderTargetVk *renderTarget = nullptr;
ANGLE_TRY(mState.getFirstColorAttachment()->getRenderTarget(&renderTarget));
renderTarget->image->updateLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
ANGLE_TRY(commandBuffer->begin());
commandBuffer->beginRenderPass(*renderPass, *framebuffer, glState.getViewport(),
attachmentClearValues);
return gl::NoError();
}
} // namespace rx
......@@ -272,4 +272,25 @@ const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const
return mLinkedFragmentModule;
}
gl::ErrorOrResult<vk::PipelineLayout *> ProgramVk::getPipelineLayout(VkDevice device)
{
vk::PipelineLayout newLayout(device);
// TODO(jmadill): Descriptor sets.
VkPipelineLayoutCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.setLayoutCount = 0;
createInfo.pSetLayouts = nullptr;
createInfo.pushConstantRangeCount = 0;
createInfo.pPushConstantRanges = nullptr;
ANGLE_TRY(newLayout.init(createInfo));
mPipelineLayout = std::move(newLayout);
return &mPipelineLayout;
}
} // namespace rx
......@@ -101,10 +101,12 @@ class ProgramVk : public ProgramImpl
const vk::ShaderModule &getLinkedVertexModule() const;
const vk::ShaderModule &getLinkedFragmentModule() const;
gl::ErrorOrResult<vk::PipelineLayout *> getPipelineLayout(VkDevice device);
private:
vk::ShaderModule mLinkedVertexModule;
vk::ShaderModule mLinkedFragmentModule;
vk::PipelineLayout mPipelineLayout;
};
} // namespace rx
......
......@@ -26,6 +26,286 @@ LoadFunctionMap Format::getLoadFunctions() const
return GetLoadFunctionsMap(internalFormat, formatID);
}
// TODO(jmadill): This is temporary. Figure out how to handle format conversions.
VkFormat GetNativeVertexFormat(gl::VertexFormatType vertexFormat)
{
switch (vertexFormat)
{
case gl::VERTEX_FORMAT_INVALID:
UNREACHABLE();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE1:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE1_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE2:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE2_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE3:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE3_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE4:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE4_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UBYTE1:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UBYTE1_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UBYTE2:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UBYTE2_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UBYTE3:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UBYTE3_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UBYTE4:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UBYTE4_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT1:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT1_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT2:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT2_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT3:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT3_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT4:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT4_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT1:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT1_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT2:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT2_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT3:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT3_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT4:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT4_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT1:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT1_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT2:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT2_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT3:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT3_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT4:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT4_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT1:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT1_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT2:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT2_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT3:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT3_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT4:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT4_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE1_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE2_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE3_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE4_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UBYTE1_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UBYTE2_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UBYTE3_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UBYTE4_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT1_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT2_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT3_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT4_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT1_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT2_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT3_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT4_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT1_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT2_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT3_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT4_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT1_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT2_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT3_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT4_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_FIXED1:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_FIXED2:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_FIXED3:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_FIXED4:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_HALF1:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_HALF2:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_HALF3:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_HALF4:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_FLOAT1:
return VK_FORMAT_R32_SFLOAT;
case gl::VERTEX_FORMAT_FLOAT2:
return VK_FORMAT_R32G32_SFLOAT;
case gl::VERTEX_FORMAT_FLOAT3:
return VK_FORMAT_R32G32B32_SFLOAT;
case gl::VERTEX_FORMAT_FLOAT4:
return VK_FORMAT_R32G32B32A32_SFLOAT;
case gl::VERTEX_FORMAT_SINT210:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT210:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT210_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT210_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT210_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT210_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
default:
UNREACHABLE();
return VK_FORMAT_UNDEFINED;
}
}
} // namespace vk
} // namespace rx
......@@ -49,6 +49,9 @@ constexpr Format::Format(GLenum internalFormat,
{
}
// TODO(jmadill): This is temporary. Figure out how to handle format conversions.
VkFormat GetNativeVertexFormat(gl::VertexFormatType vertexFormat);
} // namespace vk
} // namespace rx
......
......@@ -366,6 +366,31 @@ void CommandBuffer::endRenderPass()
vkCmdEndRenderPass(mHandle);
}
void CommandBuffer::draw(uint32_t vertexCount,
uint32_t instanceCount,
uint32_t firstVertex,
uint32_t firstInstance)
{
ASSERT(valid());
vkCmdDraw(mHandle, vertexCount, instanceCount, firstVertex, firstInstance);
}
void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint,
const vk::Pipeline &pipeline)
{
ASSERT(valid() && pipeline.valid());
vkCmdBindPipeline(mHandle, pipelineBindPoint, pipeline.getHandle());
}
void CommandBuffer::bindVertexBuffers(uint32_t firstBinding,
const std::vector<VkBuffer> &buffers,
const std::vector<VkDeviceSize> &offsets)
{
ASSERT(valid() && buffers.size() == offsets.size());
vkCmdBindVertexBuffers(mHandle, firstBinding, static_cast<uint32_t>(buffers.size()),
buffers.data(), offsets.data());
}
// Image implementation.
Image::Image() : mCurrentLayout(VK_IMAGE_LAYOUT_UNDEFINED)
{
......@@ -412,6 +437,12 @@ void Image::changeLayoutTop(VkImageAspectFlags aspectMask,
VkImageLayout newLayout,
CommandBuffer *commandBuffer)
{
if (newLayout == mCurrentLayout)
{
// No-op.
return;
}
changeLayoutWithStages(aspectMask, newLayout, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, commandBuffer);
}
......@@ -422,12 +453,6 @@ void Image::changeLayoutWithStages(VkImageAspectFlags aspectMask,
VkPipelineStageFlags dstStageMask,
CommandBuffer *commandBuffer)
{
if (newLayout == mCurrentLayout)
{
// No-op.
return;
}
VkImageMemoryBarrier imageMemoryBarrier;
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
imageMemoryBarrier.pNext = nullptr;
......@@ -842,6 +867,78 @@ Error ShaderModule::init(const VkShaderModuleCreateInfo &createInfo)
return NoError();
}
// Pipeline implementation.
Pipeline::Pipeline()
{
}
Pipeline::Pipeline(VkDevice device) : WrappedObject(device)
{
}
Pipeline::Pipeline(Pipeline &&other) : WrappedObject(std::move(other))
{
}
Pipeline::~Pipeline()
{
if (mHandle)
{
ASSERT(validDevice());
vkDestroyPipeline(mDevice, mHandle, nullptr);
}
}
Pipeline &Pipeline::operator=(Pipeline &&other)
{
std::swap(mDevice, other.mDevice);
std::swap(mHandle, other.mHandle);
return *this;
}
Error Pipeline::initGraphics(const VkGraphicsPipelineCreateInfo &createInfo)
{
ASSERT(validDevice() && !valid());
ANGLE_VK_TRY(
vkCreateGraphicsPipelines(mDevice, VK_NULL_HANDLE, 1, &createInfo, nullptr, &mHandle));
return NoError();
}
// PipelineLayout implementation.
PipelineLayout::PipelineLayout()
{
}
PipelineLayout::PipelineLayout(VkDevice device) : WrappedObject(device)
{
}
PipelineLayout::PipelineLayout(PipelineLayout &&other) : WrappedObject(std::move(other))
{
}
PipelineLayout::~PipelineLayout()
{
if (mHandle != VK_NULL_HANDLE)
{
ASSERT(validDevice());
vkDestroyPipelineLayout(mDevice, mHandle, nullptr);
}
}
PipelineLayout &PipelineLayout::operator=(PipelineLayout &&other)
{
assignOpBase(std::move(other));
return *this;
}
Error PipelineLayout::init(const VkPipelineLayoutCreateInfo &createInfo)
{
ASSERT(validDevice() && !valid());
ANGLE_VK_TRY(vkCreatePipelineLayout(mDevice, &createInfo, nullptr, &mHandle));
return NoError();
}
} // namespace vk
Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memoryProps,
......@@ -861,4 +958,69 @@ Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memory
return Optional<uint32_t>::Invalid();
}
namespace gl_vk
{
VkPrimitiveTopology GetPrimitiveTopology(GLenum mode)
{
switch (mode)
{
case GL_TRIANGLES:
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
case GL_POINTS:
return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
case GL_LINES:
return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
case GL_LINE_STRIP:
return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
case GL_TRIANGLE_FAN:
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
case GL_TRIANGLE_STRIP:
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
case GL_LINE_LOOP:
// TODO(jmadill): Implement line loop support.
UNIMPLEMENTED();
return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
default:
UNREACHABLE();
return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
}
}
VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState)
{
if (!rasterState.cullFace)
{
return VK_CULL_MODE_NONE;
}
switch (rasterState.cullMode)
{
case GL_FRONT:
return VK_CULL_MODE_FRONT_BIT;
case GL_BACK:
return VK_CULL_MODE_BACK_BIT;
case GL_FRONT_AND_BACK:
return VK_CULL_MODE_FRONT_AND_BACK;
default:
UNREACHABLE();
return VK_CULL_MODE_NONE;
}
}
VkFrontFace GetFrontFace(GLenum frontFace)
{
switch (frontFace)
{
case GL_CW:
return VK_FRONT_FACE_CLOCKWISE;
case GL_CCW:
return VK_FRONT_FACE_COUNTER_CLOCKWISE;
default:
UNREACHABLE();
return VK_FRONT_FACE_COUNTER_CLOCKWISE;
}
}
} // namespace gl_vk
} // namespace rx
......@@ -19,6 +19,7 @@ namespace gl
{
struct Box;
struct Extents;
struct RasterizerState;
struct Rectangle;
}
......@@ -42,6 +43,7 @@ namespace vk
class DeviceMemory;
class Framebuffer;
class Image;
class Pipeline;
class RenderPass;
class Error final
......@@ -141,6 +143,16 @@ class CommandBuffer final : public WrappedObject<VkCommandBuffer>
const std::vector<VkClearValue> &clearValues);
void endRenderPass();
void draw(uint32_t vertexCount,
uint32_t instanceCount,
uint32_t firstVertex,
uint32_t firstInstance);
void bindPipeline(VkPipelineBindPoint pipelineBindPoint, const vk::Pipeline &pipeline);
void bindVertexBuffers(uint32_t firstBinding,
const std::vector<VkBuffer> &buffers,
const std::vector<VkDeviceSize> &offsets);
private:
VkCommandPool mCommandPool;
};
......@@ -302,12 +314,43 @@ class ShaderModule final : public WrappedObject<VkShaderModule>
Error init(const VkShaderModuleCreateInfo &createInfo);
};
class Pipeline final : public WrappedObject<VkPipeline>
{
public:
Pipeline();
Pipeline(VkDevice device);
Pipeline(Pipeline &&other);
~Pipeline();
Pipeline &operator=(Pipeline &&other);
Error initGraphics(const VkGraphicsPipelineCreateInfo &createInfo);
};
class PipelineLayout final : public WrappedObject<VkPipelineLayout>
{
public:
PipelineLayout();
PipelineLayout(VkDevice device);
PipelineLayout(PipelineLayout &&other);
~PipelineLayout();
PipelineLayout &operator=(PipelineLayout &&other);
Error init(const VkPipelineLayoutCreateInfo &createInfo);
};
} // namespace vk
Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memoryProps,
const VkMemoryRequirements &requirements,
uint32_t propertyFlagMask);
namespace gl_vk
{
VkPrimitiveTopology GetPrimitiveTopology(GLenum mode);
VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState);
VkFrontFace GetFrontFace(GLenum frontFace);
} // namespace gl_vk
} // namespace rx
#define ANGLE_VK_TRY(command) \
......
......@@ -236,6 +236,54 @@ TEST_P(SimpleOperationTest, BufferSubData)
EXPECT_GL_NO_ERROR();
}
// Simple quad test.
TEST_P(SimpleOperationTest, DrawQuad)
{
const std::string &vertexShader =
"attribute vec3 position;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(position, 1);\n"
"}";
const std::string &fragmentShader =
"void main()\n"
"{\n"
" gl_FragColor = vec4(0, 1, 0, 1);\n"
"}";
ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
drawQuad(program.get(), "position", 0.5f, 1.0f, true);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// Simple repeatd draw and swap test.
TEST_P(SimpleOperationTest, DrawQuadAndSwap)
{
const std::string &vertexShader =
"attribute vec3 position;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(position, 1);\n"
"}";
const std::string &fragmentShader =
"void main()\n"
"{\n"
" gl_FragColor = vec4(0, 1, 0, 1);\n"
"}";
ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
for (int i = 0; i < 8; ++i)
{
drawQuad(program.get(), "position", 0.5f, 1.0f, true);
EXPECT_GL_NO_ERROR();
swapBuffers();
}
EXPECT_GL_NO_ERROR();
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(SimpleOperationTest,
ES2_D3D9(),
......
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