2022-07-14 13:52:29 +02:00
|
|
|
#include "d3d9_constant_buffer.h"
|
|
|
|
#include "d3d9_device.h"
|
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
|
|
|
D3D9ConstantBuffer::D3D9ConstantBuffer() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
D3D9ConstantBuffer::D3D9ConstantBuffer(
|
|
|
|
D3D9DeviceEx* pDevice,
|
|
|
|
DxsoProgramType ShaderStage,
|
|
|
|
DxsoConstantBuffers BufferType,
|
|
|
|
VkDeviceSize Size)
|
2022-07-31 02:39:20 +02:00
|
|
|
: D3D9ConstantBuffer(pDevice, GetShaderStage(ShaderStage),
|
|
|
|
computeResourceSlotId(ShaderStage, DxsoBindingType::ConstantBuffer, BufferType),
|
|
|
|
Size) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
D3D9ConstantBuffer::D3D9ConstantBuffer(
|
|
|
|
D3D9DeviceEx* pDevice,
|
|
|
|
VkShaderStageFlags Stages,
|
|
|
|
uint32_t ResourceSlot,
|
|
|
|
VkDeviceSize Size)
|
2022-07-14 13:52:29 +02:00
|
|
|
: m_device (pDevice)
|
2022-07-31 02:39:20 +02:00
|
|
|
, m_binding (ResourceSlot)
|
|
|
|
, m_stages (Stages)
|
2022-07-14 13:52:29 +02:00
|
|
|
, 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)
|
2022-08-03 16:14:57 +02:00
|
|
|
] (DxvkContext* ctx) mutable {
|
|
|
|
ctx->bindResourceBuffer(cStages, cBinding, std::move(cSlice));
|
2022-07-14 13:52:29 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|