blob: 15ca724136a6f41eef7239d68dc7cc4fe030e80d [file] [log] [blame]
//
// Copyright (c) 2013 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.
//
// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation.
#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/VertexAttribute.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
namespace rx
{
VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) : mRenderer(renderer)
{
mBuffer = nullptr;
mBufferSize = 0;
mDynamicUsage = false;
mMappedResourceData = nullptr;
}
VertexBuffer11::~VertexBuffer11()
{
ASSERT(mMappedResourceData == nullptr);
SafeRelease(mBuffer);
}
gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage)
{
SafeRelease(mBuffer);
updateSerial();
if (size > 0)
{
ID3D11Device *dxDevice = mRenderer->getDevice();
D3D11_BUFFER_DESC bufferDesc;
bufferDesc.ByteWidth = size;
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bufferDesc.MiscFlags = 0;
bufferDesc.StructureByteStride = 0;
HRESULT result = dxDevice->CreateBuffer(&bufferDesc, nullptr, &mBuffer);
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY,
"Failed to allocate internal vertex buffer of size, %lu.", size);
}
if (dynamicUsage)
{
d3d11::SetDebugName(mBuffer, "VertexBuffer11 (dynamic)");
}
else
{
d3d11::SetDebugName(mBuffer, "VertexBuffer11 (static)");
}
}
mBufferSize = size;
mDynamicUsage = dynamicUsage;
return gl::NoError();
}
gl::Error VertexBuffer11::mapResource()
{
if (mMappedResourceData == nullptr)
{
ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT result =
dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY,
"Failed to map internal vertex buffer, HRESULT: 0x%08x.", result);
}
mMappedResourceData = reinterpret_cast<uint8_t *>(mappedResource.pData);
}
return gl::NoError();
}
void VertexBuffer11::hintUnmapResource()
{
if (mMappedResourceData != nullptr)
{
ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
dxContext->Unmap(mBuffer, 0);
mMappedResourceData = nullptr;
}
}
gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib,
const gl::VertexBinding &binding,
GLenum currentValueType,
GLint start,
GLsizei count,
GLsizei instances,
unsigned int offset,
const uint8_t *sourceData)
{
if (!mBuffer)
{
return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
}
int inputStride = static_cast<int>(ComputeVertexAttributeStride(attrib, binding));
// This will map the resource if it isn't already mapped.
ANGLE_TRY(mapResource());
uint8_t *output = mMappedResourceData + offset;
const uint8_t *input = sourceData;
if (instances == 0 || binding.divisor == 0)
{
input += inputStride * start;
}
gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType);
const D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel;
const d3d11::VertexFormat &vertexFormatInfo =
d3d11::GetVertexFormatInfo(vertexFormatType, featureLevel);
ASSERT(vertexFormatInfo.copyFunction != nullptr);
vertexFormatInfo.copyFunction(input, inputStride, count, output);
return gl::NoError();
}
unsigned int VertexBuffer11::getBufferSize() const
{
return mBufferSize;
}
gl::Error VertexBuffer11::setBufferSize(unsigned int size)
{
if (size > mBufferSize)
{
return initialize(size, mDynamicUsage);
}
else
{
return gl::NoError();
}
}
gl::Error VertexBuffer11::discard()
{
if (!mBuffer)
{
return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
}
ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY,
"Failed to map internal buffer for discarding, HRESULT: 0x%08x", result);
}
dxContext->Unmap(mBuffer, 0);
return gl::NoError();
}
ID3D11Buffer *VertexBuffer11::getBuffer() const
{
return mBuffer;
}
} // namespace rx