mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-28 02:19:26 +01:00
[dxvk,d3d9,d3d11] Refactor input layout objects
This commit is contained in:
parent
f3a2dd54c3
commit
1582567ed2
@ -3326,14 +3326,20 @@ namespace dxvk {
|
||||
|
||||
template<typename ContextType>
|
||||
void D3D11CommonContext<ContextType>::ApplyInputLayout() {
|
||||
auto inputLayout = m_state.ia.inputLayout.prvRef();
|
||||
if (likely(m_state.ia.inputLayout != nullptr)) {
|
||||
uint32_t attributeCount = m_state.ia.inputLayout->GetAttributeCount();
|
||||
uint32_t bindingCount = m_state.ia.inputLayout->GetBindingCount();
|
||||
|
||||
if (likely(inputLayout != nullptr)) {
|
||||
EmitCs([
|
||||
cInputLayout = std::move(inputLayout)
|
||||
] (DxvkContext* ctx) {
|
||||
cInputLayout->BindToContext(ctx);
|
||||
EmitCsCmd<DxvkVertexInput>(D3D11CmdType::None, attributeCount + bindingCount, [
|
||||
cAttributeCount = attributeCount,
|
||||
cBindingCount = bindingCount
|
||||
] (DxvkContext* ctx, const DxvkVertexInput* layout, size_t) {
|
||||
ctx->setInputLayout(cAttributeCount, &layout[0],
|
||||
cBindingCount, &layout[cAttributeCount]);
|
||||
});
|
||||
|
||||
for (uint32_t i = 0; i < attributeCount + bindingCount; i++)
|
||||
new (m_csData->at(i)) DxvkVertexInput(m_state.ia.inputLayout->GetInput(i));
|
||||
} else {
|
||||
EmitCs([] (DxvkContext* ctx) {
|
||||
ctx->setInputLayout(0, nullptr, 0, nullptr);
|
||||
|
@ -668,29 +668,29 @@ namespace dxvk {
|
||||
// works, provided the shader does not have any actual inputs
|
||||
if (!pInputElementDescs)
|
||||
return E_INVALIDARG;
|
||||
|
||||
|
||||
try {
|
||||
DxbcReader dxbcReader(reinterpret_cast<const char*>(
|
||||
pShaderBytecodeWithInputSignature), BytecodeLength);
|
||||
DxbcModule dxbcModule(dxbcReader);
|
||||
|
||||
|
||||
const Rc<DxbcIsgn> inputSignature = dxbcModule.isgn();
|
||||
|
||||
uint32_t attrMask = 0;
|
||||
uint32_t bindMask = 0;
|
||||
uint32_t locationMask = 0;
|
||||
uint32_t bindingsDefined = 0;
|
||||
|
||||
|
||||
std::array<DxvkVertexAttribute, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> attrList = { };
|
||||
std::array<DxvkVertexBinding, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> bindList = { };
|
||||
|
||||
|
||||
for (uint32_t i = 0; i < NumElements; i++) {
|
||||
const DxbcSgnEntry* entry = inputSignature->find(
|
||||
pInputElementDescs[i].SemanticName,
|
||||
pInputElementDescs[i].SemanticIndex, 0);
|
||||
|
||||
// Create vertex input attribute description
|
||||
DxvkVertexAttribute attrib;
|
||||
DxvkVertexAttribute attrib = { };
|
||||
attrib.location = entry != nullptr ? entry->registerId : 0;
|
||||
attrib.binding = pInputElementDescs[i].InputSlot;
|
||||
attrib.format = LookupFormat(pInputElementDescs[i].Format, DXGI_VK_FORMAT_MODE_COLOR).Format;
|
||||
@ -714,17 +714,18 @@ namespace dxvk {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (attrib.offset & (alignment - 1))
|
||||
} else if (attrib.offset & (alignment - 1)) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
attrList.at(i) = attrib;
|
||||
|
||||
// Create vertex input binding description. The
|
||||
// stride is dynamic state in D3D11 and will be
|
||||
// set by D3D11DeviceContext::IASetVertexBuffers.
|
||||
DxvkVertexBinding binding;
|
||||
DxvkVertexBinding binding = { };
|
||||
binding.binding = pInputElementDescs[i].InputSlot;
|
||||
binding.fetchRate = pInputElementDescs[i].InstanceDataStepRate;
|
||||
binding.divisor = pInputElementDescs[i].InstanceDataStepRate;
|
||||
binding.inputRate = pInputElementDescs[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA
|
||||
? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
binding.extent = entry ? uint32_t(attrib.offset + formatInfo->elementSize) : 0u;
|
||||
|
@ -10,23 +10,22 @@ namespace dxvk {
|
||||
uint32_t numBindings,
|
||||
const DxvkVertexBinding* pBindings)
|
||||
: D3D11DeviceChild<ID3D11InputLayout>(pDevice),
|
||||
m_d3d10(this) {
|
||||
m_attributes.resize(numAttributes);
|
||||
m_bindings.resize(numBindings);
|
||||
|
||||
m_attributeCount (numAttributes),
|
||||
m_bindingCount (numBindings),
|
||||
m_d3d10 (this) {
|
||||
for (uint32_t i = 0; i < numAttributes; i++)
|
||||
m_attributes.at(i) = pAttributes[i];
|
||||
|
||||
m_input.inputs[i] = DxvkVertexInput(pAttributes[i]);
|
||||
|
||||
for (uint32_t i = 0; i < numBindings; i++)
|
||||
m_bindings.at(i) = pBindings[i];
|
||||
m_input.inputs[i + numAttributes] = DxvkVertexInput(pBindings[i]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
D3D11InputLayout::~D3D11InputLayout() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE D3D11InputLayout::QueryInterface(REFIID riid, void** ppvObject) {
|
||||
if (ppvObject == nullptr)
|
||||
return E_POINTER;
|
||||
@ -55,33 +54,11 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void D3D11InputLayout::BindToContext(DxvkContext* ctx) {
|
||||
ctx->setInputLayout(
|
||||
m_attributes.size(),
|
||||
m_attributes.data(),
|
||||
m_bindings.size(),
|
||||
m_bindings.data());
|
||||
}
|
||||
|
||||
|
||||
bool D3D11InputLayout::Compare(const D3D11InputLayout* pOther) const {
|
||||
bool eq = m_attributes.size() == pOther->m_attributes.size()
|
||||
&& m_bindings.size() == pOther->m_bindings.size();
|
||||
|
||||
for (uint32_t i = 0; eq && i < m_attributes.size(); i++) {
|
||||
eq &= m_attributes[i].location == pOther->m_attributes[i].location
|
||||
&& m_attributes[i].binding == pOther->m_attributes[i].binding
|
||||
&& m_attributes[i].format == pOther->m_attributes[i].format
|
||||
&& m_attributes[i].offset == pOther->m_attributes[i].offset;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; eq && i < m_bindings.size(); i++) {
|
||||
eq &= m_bindings[i].binding == pOther->m_bindings[i].binding
|
||||
&& m_bindings[i].fetchRate == pOther->m_bindings[i].fetchRate
|
||||
&& m_bindings[i].inputRate == pOther->m_bindings[i].inputRate;
|
||||
}
|
||||
|
||||
return eq;
|
||||
if (m_attributeCount != pOther->m_attributeCount || m_bindingCount != pOther->m_bindingCount)
|
||||
return false;
|
||||
|
||||
return bit::bcmpeq(&m_input, &pOther->m_input);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,7 +7,12 @@
|
||||
namespace dxvk {
|
||||
|
||||
class D3D11Device;
|
||||
|
||||
|
||||
struct alignas(16) D3D11VertexInput {
|
||||
std::array<DxvkVertexInput, MaxNumVertexAttributes + MaxNumVertexBindings> inputs;
|
||||
};
|
||||
|
||||
|
||||
class D3D11InputLayout : public D3D11DeviceChild<ID3D11InputLayout> {
|
||||
|
||||
public:
|
||||
@ -24,9 +29,19 @@ namespace dxvk {
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(
|
||||
REFIID riid,
|
||||
void** ppvObject) final;
|
||||
|
||||
void BindToContext(DxvkContext* ctx);
|
||||
|
||||
|
||||
uint32_t GetAttributeCount() const {
|
||||
return m_attributeCount;
|
||||
}
|
||||
|
||||
uint32_t GetBindingCount() const {
|
||||
return m_bindingCount;
|
||||
}
|
||||
|
||||
DxvkVertexInput GetInput(uint32_t Index) const {
|
||||
return m_input.inputs[Index];
|
||||
}
|
||||
|
||||
bool Compare(
|
||||
const D3D11InputLayout* pOther) const;
|
||||
|
||||
@ -35,9 +50,11 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::vector<DxvkVertexAttribute> m_attributes;
|
||||
std::vector<DxvkVertexBinding> m_bindings;
|
||||
|
||||
D3D11VertexInput m_input = { };
|
||||
|
||||
uint32_t m_attributeCount = 0;
|
||||
uint32_t m_bindingCount = 0;
|
||||
|
||||
D3D10InputLayout m_d3d10;
|
||||
|
||||
|
@ -7521,8 +7521,9 @@ namespace dxvk {
|
||||
|
||||
const auto& elements = cVertexDecl->GetElements();
|
||||
|
||||
std::array<DxvkVertexAttribute, 2 * caps::InputRegisterCount> attrList;
|
||||
std::array<DxvkVertexBinding, 2 * caps::InputRegisterCount> bindList;
|
||||
std::array<DxvkVertexInput, 2 * caps::InputRegisterCount> attrList = { };
|
||||
std::array<DxvkVertexInput, 2 * caps::InputRegisterCount> bindList = { };
|
||||
std::array<uint32_t, 2 * caps::InputRegisterCount> vertexSizes = { };
|
||||
|
||||
uint32_t attrMask = 0;
|
||||
uint32_t bindMask = 0;
|
||||
@ -7534,7 +7535,7 @@ namespace dxvk {
|
||||
for (uint32_t i = 0; i < isgn.elemCount; i++) {
|
||||
const auto& decl = isgn.elems[i];
|
||||
|
||||
DxvkVertexAttribute attrib;
|
||||
DxvkVertexAttribute attrib = { };
|
||||
attrib.location = i;
|
||||
attrib.binding = NullStreamIdx;
|
||||
attrib.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||
@ -7555,28 +7556,26 @@ namespace dxvk {
|
||||
}
|
||||
}
|
||||
|
||||
attrList[i] = attrib;
|
||||
attrList[i] = DxvkVertexInput(attrib);
|
||||
|
||||
DxvkVertexBinding binding;
|
||||
vertexSizes[attrib.binding] = std::max(vertexSizes[attrib.binding],
|
||||
uint32_t(attrib.offset + lookupFormatInfo(attrib.format)->elementSize));
|
||||
|
||||
DxvkVertexBinding binding = { };
|
||||
binding.binding = attrib.binding;
|
||||
binding.extent = attrib.offset + lookupFormatInfo(attrib.format)->elementSize;
|
||||
binding.extent = vertexSizes[attrib.binding];
|
||||
|
||||
uint32_t instanceData = cStreamFreq[binding.binding % caps::MaxStreams];
|
||||
if (instanceData & D3DSTREAMSOURCE_INSTANCEDATA) {
|
||||
binding.fetchRate = instanceData & 0x7FFFFF; // Remove instance packed-in flags in the data.
|
||||
binding.divisor = instanceData & 0x7FFFFF; // Remove instance packed-in flags in the data.
|
||||
binding.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
|
||||
}
|
||||
else {
|
||||
binding.fetchRate = 0;
|
||||
binding.divisor = 0u;
|
||||
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
}
|
||||
|
||||
if (bindMask & (1u << binding.binding)) {
|
||||
bindList.at(binding.binding).extent = std::max(
|
||||
bindList.at(binding.binding).extent, binding.extent);
|
||||
} else {
|
||||
bindList.at(binding.binding) = binding;
|
||||
}
|
||||
bindList[binding.binding] = DxvkVertexInput(binding);
|
||||
|
||||
attrMask |= 1u << i;
|
||||
bindMask |= 1u << binding.binding;
|
||||
|
@ -539,9 +539,6 @@ namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Vertex attribute description
|
||||
*
|
||||
* Stores information about a
|
||||
* single vertex attribute.
|
||||
*/
|
||||
struct DxvkVertexAttribute {
|
||||
uint32_t location;
|
||||
@ -549,34 +546,113 @@ namespace dxvk {
|
||||
VkFormat format;
|
||||
uint32_t offset;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief Vertex binding description
|
||||
*
|
||||
* Stores information about a
|
||||
* single vertex binding slot.
|
||||
* \brief Packed vertex attribute
|
||||
*
|
||||
* Compact representation of a vertex attribute.
|
||||
*/
|
||||
struct DxvkVertexBinding {
|
||||
uint32_t binding;
|
||||
uint32_t fetchRate;
|
||||
VkVertexInputRate inputRate;
|
||||
uint32_t extent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Input layout
|
||||
*
|
||||
* Stores the description of all active
|
||||
* vertex attributes and vertex bindings.
|
||||
*/
|
||||
struct DxvkInputLayout {
|
||||
uint32_t numAttributes;
|
||||
uint32_t numBindings;
|
||||
|
||||
std::array<DxvkVertexAttribute, DxvkLimits::MaxNumVertexAttributes> attributes;
|
||||
std::array<DxvkVertexBinding, DxvkLimits::MaxNumVertexBindings> bindings;
|
||||
struct DxvkPackedVertexAttribute {
|
||||
DxvkPackedVertexAttribute() = default;
|
||||
DxvkPackedVertexAttribute(const DxvkVertexAttribute& a)
|
||||
: location (a.location),
|
||||
binding (a.binding),
|
||||
format (uint32_t(a.format)),
|
||||
offset (a.offset),
|
||||
reserved (0u) { }
|
||||
|
||||
uint32_t location : 5;
|
||||
uint32_t binding : 5;
|
||||
uint32_t format : 7;
|
||||
uint32_t offset : 11;
|
||||
uint32_t reserved : 4;
|
||||
|
||||
DxvkVertexAttribute unpack() const {
|
||||
DxvkVertexAttribute result = { };
|
||||
result.location = location;
|
||||
result.binding = binding;
|
||||
result.format = VkFormat(format);
|
||||
result.offset = offset;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Vertex binding description
|
||||
*/
|
||||
struct DxvkVertexBinding {
|
||||
uint32_t binding;
|
||||
uint32_t extent;
|
||||
VkVertexInputRate inputRate;
|
||||
uint32_t divisor;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Packed vertex attribute
|
||||
*
|
||||
* Compact representation of a vertex binding.
|
||||
*/
|
||||
struct DxvkPackedVertexBinding {
|
||||
DxvkPackedVertexBinding() = default;
|
||||
DxvkPackedVertexBinding(const DxvkVertexBinding& b)
|
||||
: binding (b.binding),
|
||||
extent (b.extent),
|
||||
inputRate (uint32_t(b.inputRate)),
|
||||
divisor (b.divisor < (1u << 14) ? b.divisor : 0u) { }
|
||||
|
||||
uint32_t binding : 5;
|
||||
uint32_t extent : 12;
|
||||
uint32_t inputRate : 1;
|
||||
uint32_t divisor : 14;
|
||||
|
||||
DxvkVertexBinding unpack() const {
|
||||
DxvkVertexBinding result = { };
|
||||
result.binding = binding;
|
||||
result.extent = extent;
|
||||
result.inputRate = VkVertexInputRate(inputRate);
|
||||
result.divisor = divisor;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Packed attribute binding
|
||||
*
|
||||
* Relies on attriute and bining
|
||||
* structures to have the same size.
|
||||
*/
|
||||
class DxvkVertexInput {
|
||||
|
||||
public:
|
||||
|
||||
DxvkVertexInput() = default;
|
||||
|
||||
DxvkVertexInput(const DxvkVertexAttribute& attribute)
|
||||
: m_attribute(attribute) { }
|
||||
|
||||
DxvkVertexInput(const DxvkVertexBinding& binding)
|
||||
: m_binding(binding) { }
|
||||
|
||||
DxvkVertexAttribute attribute() const {
|
||||
return m_attribute.unpack();
|
||||
}
|
||||
|
||||
DxvkVertexBinding binding() const {
|
||||
return m_binding.unpack();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
union {
|
||||
DxvkPackedVertexAttribute m_attribute;
|
||||
DxvkPackedVertexBinding m_binding;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
static_assert(sizeof(DxvkVertexInput) == sizeof(uint32_t));
|
||||
|
||||
}
|
||||
|
@ -2694,38 +2694,45 @@ namespace dxvk {
|
||||
|
||||
void DxvkContext::setInputLayout(
|
||||
uint32_t attributeCount,
|
||||
const DxvkVertexAttribute* attributes,
|
||||
const DxvkVertexInput* attributes,
|
||||
uint32_t bindingCount,
|
||||
const DxvkVertexBinding* bindings) {
|
||||
const DxvkVertexInput* bindings) {
|
||||
m_flags.set(
|
||||
DxvkContextFlag::GpDirtyPipelineState,
|
||||
DxvkContextFlag::GpDirtyVertexBuffers);
|
||||
|
||||
for (uint32_t i = 0; i < bindingCount; i++) {
|
||||
auto binding = bindings[i].binding();
|
||||
|
||||
m_state.gp.state.ilBindings[i] = DxvkIlBinding(
|
||||
bindings[i].binding, 0, bindings[i].inputRate,
|
||||
bindings[i].fetchRate);
|
||||
m_state.vi.vertexExtents[i] = bindings[i].extent;
|
||||
binding.binding, 0,
|
||||
binding.inputRate,
|
||||
binding.divisor);
|
||||
m_state.vi.vertexExtents[i] = binding.extent;
|
||||
}
|
||||
|
||||
for (uint32_t i = bindingCount; i < m_state.gp.state.il.bindingCount(); i++) {
|
||||
m_state.gp.state.ilBindings[i] = DxvkIlBinding();
|
||||
m_state.vi.vertexExtents[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
for (uint32_t i = 0; i < attributeCount; i++) {
|
||||
auto attribute = attributes[i].attribute();
|
||||
|
||||
m_state.gp.state.ilAttributes[i] = DxvkIlAttribute(
|
||||
attributes[i].location, attributes[i].binding,
|
||||
attributes[i].format, attributes[i].offset);
|
||||
attribute.location,
|
||||
attribute.binding,
|
||||
attribute.format,
|
||||
attribute.offset);
|
||||
}
|
||||
|
||||
|
||||
for (uint32_t i = attributeCount; i < m_state.gp.state.il.attributeCount(); i++)
|
||||
m_state.gp.state.ilAttributes[i] = DxvkIlAttribute();
|
||||
|
||||
|
||||
m_state.gp.state.il = DxvkIlInfo(attributeCount, bindingCount);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void DxvkContext::setRasterizerState(const DxvkRasterizerState& rs) {
|
||||
VkCullModeFlags cullMode = rs.cullMode();
|
||||
VkFrontFace frontFace = rs.frontFace();
|
||||
|
@ -1187,16 +1187,16 @@ namespace dxvk {
|
||||
* \brief Sets input layout
|
||||
*
|
||||
* \param [in] attributeCount Number of vertex attributes
|
||||
* \param [in] attributes The vertex attributes
|
||||
* \param [in] attributes Array of attribute infos
|
||||
* \param [in] bindingCount Number of buffer bindings
|
||||
* \param [in] bindings Vertex buffer bindigs
|
||||
* \param [in] bindings Array of binding infos
|
||||
*/
|
||||
void setInputLayout(
|
||||
uint32_t attributeCount,
|
||||
const DxvkVertexAttribute* attributes,
|
||||
const DxvkVertexInput* attributes,
|
||||
uint32_t bindingCount,
|
||||
const DxvkVertexBinding* bindings);
|
||||
|
||||
const DxvkVertexInput* bindings);
|
||||
|
||||
/**
|
||||
* \brief Sets rasterizer state
|
||||
* \param [in] rs New state object
|
||||
|
Loading…
x
Reference in New Issue
Block a user