blob: 3238c962ac3807963540918f88b31a7e73573fa8 [file] [log] [blame]
//
// Copyright (c) 2012 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.
//
// IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation.
#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
namespace rx
{
IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer)
{
mBuffer = nullptr;
mBufferSize = 0;
mDynamicUsage = false;
}
IndexBuffer11::~IndexBuffer11()
{
SafeRelease(mBuffer);
}
gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
{
SafeRelease(mBuffer);
updateSerial();
if (bufferSize > 0)
{
ID3D11Device* dxDevice = mRenderer->getDevice();
D3D11_BUFFER_DESC bufferDesc;
bufferDesc.ByteWidth = bufferSize;
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
bufferDesc.BindFlags = D3D11_BIND_INDEX_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 index buffer of size, %lu.", bufferSize);
}
if (dynamic)
{
d3d11::SetDebugName(mBuffer, "IndexBuffer11 (dynamic)");
}
else
{
d3d11::SetDebugName(mBuffer, "IndexBuffer11 (static)");
}
}
mBufferSize = bufferSize;
mIndexType = indexType;
mDynamicUsage = dynamic;
return gl::NoError();
}
gl::Error IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
{
if (!mBuffer)
{
return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
}
// Check for integer overflows and out-out-bounds map requests
if (offset + size < offset || offset + size > mBufferSize)
{
return gl::Error(GL_OUT_OF_MEMORY, "Index buffer map range is not inside the buffer.");
}
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 index buffer, HRESULT: 0x%08x.", result);
}
*outMappedMemory = reinterpret_cast<char*>(mappedResource.pData) + offset;
return gl::NoError();
}
gl::Error IndexBuffer11::unmapBuffer()
{
if (!mBuffer)
{
return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
}
ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
dxContext->Unmap(mBuffer, 0);
return gl::NoError();
}
GLenum IndexBuffer11::getIndexType() const
{
return mIndexType;
}
unsigned int IndexBuffer11::getBufferSize() const
{
return mBufferSize;
}
gl::Error IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType)
{
if (bufferSize > mBufferSize || indexType != mIndexType)
{
return initialize(bufferSize, indexType, mDynamicUsage);
}
else
{
return gl::NoError();
}
}
gl::Error IndexBuffer11::discard()
{
if (!mBuffer)
{
return gl::Error(GL_OUT_OF_MEMORY, "Internal index 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 index buffer, HRESULT: 0x%08x.", result);
}
dxContext->Unmap(mBuffer, 0);
return gl::NoError();
}
DXGI_FORMAT IndexBuffer11::getIndexFormat() const
{
switch (mIndexType)
{
case GL_UNSIGNED_BYTE: return DXGI_FORMAT_R16_UINT;
case GL_UNSIGNED_SHORT: return DXGI_FORMAT_R16_UINT;
case GL_UNSIGNED_INT: return DXGI_FORMAT_R32_UINT;
default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN;
}
}
ID3D11Buffer *IndexBuffer11::getBuffer() const
{
return mBuffer;
}
}