mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-22 14:52:18 +01:00
122 lines
3.3 KiB
C++
122 lines
3.3 KiB
C++
|
#include "d3d9_constant_buffer.h"
|
||
|
#include "d3d9_device.h"
|
||
|
|
||
|
namespace dxvk {
|
||
|
|
||
|
D3D9ConstantBuffer::D3D9ConstantBuffer() {
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
D3D9ConstantBuffer::D3D9ConstantBuffer(
|
||
|
D3D9DeviceEx* pDevice,
|
||
|
DxsoProgramType ShaderStage,
|
||
|
DxsoConstantBuffers BufferType,
|
||
|
VkDeviceSize Size)
|
||
|
: m_device (pDevice)
|
||
|
, m_binding (computeResourceSlotId(ShaderStage, DxsoBindingType::ConstantBuffer, BufferType))
|
||
|
, m_stages (GetShaderStage(ShaderStage))
|
||
|
, m_size (Size)
|
||
|
, m_align (getAlignment(pDevice->GetDXVKDevice())) {
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
D3D9ConstantBuffer::~D3D9ConstantBuffer() {
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void* D3D9ConstantBuffer::Alloc(VkDeviceSize size) {
|
||
|
if (unlikely(m_buffer == nullptr)) {
|
||
|
this->createBuffer();
|
||
|
m_slice = m_buffer->getSliceHandle();
|
||
|
}
|
||
|
|
||
|
size = align(size, m_align);
|
||
|
|
||
|
if (unlikely(m_offset + size > m_size)) {
|
||
|
m_slice = m_buffer->allocSlice();
|
||
|
m_offset = 0;
|
||
|
|
||
|
m_device->EmitCs([
|
||
|
cBuffer = m_buffer,
|
||
|
cSlice = m_slice
|
||
|
] (DxvkContext* ctx) {
|
||
|
ctx->invalidateBuffer(cBuffer, cSlice);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
m_device->EmitCs([
|
||
|
cStages = m_stages,
|
||
|
cBinding = m_binding,
|
||
|
cOffset = m_offset,
|
||
|
cLength = size
|
||
|
] (DxvkContext* ctx) {
|
||
|
ctx->bindResourceBufferRange(cStages, cBinding, cOffset, cLength);
|
||
|
});
|
||
|
|
||
|
void* mapPtr = reinterpret_cast<char*>(m_slice.mapPtr) + m_offset;
|
||
|
m_offset += size;
|
||
|
return mapPtr;
|
||
|
}
|
||
|
|
||
|
|
||
|
void* D3D9ConstantBuffer::AllocSlice() {
|
||
|
if (unlikely(m_buffer == nullptr))
|
||
|
this->createBuffer();
|
||
|
|
||
|
m_slice = m_buffer->allocSlice();
|
||
|
|
||
|
m_device->EmitCs([
|
||
|
cBuffer = m_buffer,
|
||
|
cSlice = m_slice
|
||
|
] (DxvkContext* ctx) {
|
||
|
ctx->invalidateBuffer(cBuffer, cSlice);
|
||
|
});
|
||
|
|
||
|
return m_slice.mapPtr;
|
||
|
}
|
||
|
|
||
|
|
||
|
void D3D9ConstantBuffer::createBuffer() {
|
||
|
auto options = m_device->GetOptions();
|
||
|
|
||
|
// Buffer usage and access flags don't make much of a difference
|
||
|
// in the backend, so set both STORAGE and UNIFORM usage/access.
|
||
|
DxvkBufferCreateInfo bufferInfo;
|
||
|
bufferInfo.size = align(m_size, m_align);
|
||
|
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
|
||
|
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||
|
bufferInfo.access = VK_ACCESS_UNIFORM_READ_BIT
|
||
|
| VK_ACCESS_SHADER_READ_BIT;
|
||
|
bufferInfo.stages = util::pipelineStages(m_stages);
|
||
|
|
||
|
VkMemoryPropertyFlags memoryFlags
|
||
|
= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
||
|
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
||
|
|
||
|
if (options->deviceLocalConstantBuffers)
|
||
|
memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||
|
|
||
|
m_buffer = m_device->GetDXVKDevice()->createBuffer(bufferInfo, memoryFlags);
|
||
|
|
||
|
m_device->EmitCs([
|
||
|
cStages = m_stages,
|
||
|
cBinding = m_binding,
|
||
|
cSlice = DxvkBufferSlice(m_buffer)
|
||
|
] (DxvkContext* ctx) {
|
||
|
ctx->bindResourceBuffer(cStages, cBinding, cSlice);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
|
||
|
VkDeviceSize D3D9ConstantBuffer::getAlignment(const Rc<DxvkDevice>& device) const {
|
||
|
return std::max(std::max(
|
||
|
device->properties().core.properties.limits.minUniformBufferOffsetAlignment,
|
||
|
device->properties().core.properties.limits.minStorageBufferOffsetAlignment),
|
||
|
device->properties().extRobustness2.robustUniformBufferAccessSizeAlignment);
|
||
|
}
|
||
|
|
||
|
}
|