[d3d11] Implemented input layout creation

This commit is contained in:
Philip Rebohle 2017-12-07 12:45:02 +01:00
parent f33acf7334
commit 1f89452014
9 changed files with 204 additions and 6 deletions

View File

@ -58,7 +58,7 @@ namespace dxvk {
void D3D11DeviceContext::ClearState() {
// this->IASetInputLayout(nullptr);
this->IASetInputLayout(nullptr);
this->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED);
// this->IASetVertexBuffers(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, nullptr, nullptr, nullptr);
// this->IASetIndexBuffer(nullptr, DXGI_FORMAT_UNKNOWN, 0);
@ -424,7 +424,15 @@ namespace dxvk {
void D3D11DeviceContext::IASetInputLayout(ID3D11InputLayout* pInputLayout) {
Logger::err("D3D11DeviceContext::IASetInputLayout: Not implemented");
auto inputLayout = static_cast<D3D11InputLayout*>(pInputLayout);
if (m_state.ia.inputLayout != inputLayout) {
m_state.ia.inputLayout = inputLayout;
m_context->setInputLayout(inputLayout != nullptr
? inputLayout->GetDXVKInputLayout()
: nullptr);
}
}
@ -522,7 +530,7 @@ namespace dxvk {
void D3D11DeviceContext::IAGetInputLayout(ID3D11InputLayout** ppInputLayout) {
Logger::err("D3D11DeviceContext::IAGetInputLayout: Not implemented");
*ppInputLayout = m_state.ia.inputLayout.ref();
}
@ -822,7 +830,7 @@ namespace dxvk {
auto shader = static_cast<D3D11PixelShader*>(pPixelShader);
if (NumClassInstances != 0)
Logger::err("D3D11DeviceContext::VSSetShader: Class instances not supported");
Logger::err("D3D11DeviceContext::PSSetShader: Class instances not supported");
if (m_state.ps.shader != shader) {
m_state.ps.shader = shader;

View File

@ -3,6 +3,7 @@
#include <array>
#include "d3d11_buffer.h"
#include "d3d11_input_layout.h"
#include "d3d11_shader.h"
#include "d3d11_state.h"
#include "d3d11_view.h"
@ -61,6 +62,7 @@ namespace dxvk {
struct D3D11ContextStateIA {
Com<D3D11InputLayout> inputLayout;
D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
};

View File

@ -3,6 +3,7 @@
#include "d3d11_buffer.h"
#include "d3d11_context.h"
#include "d3d11_device.h"
#include "d3d11_input_layout.h"
#include "d3d11_present.h"
#include "d3d11_shader.h"
#include "d3d11_texture.h"
@ -261,8 +262,98 @@ namespace dxvk {
const void* pShaderBytecodeWithInputSignature,
SIZE_T BytecodeLength,
ID3D11InputLayout** ppInputLayout) {
Logger::err("D3D11Device::CreateInputLayout: Not implemented");
return E_NOTIMPL;
try {
DxbcReader dxbcReader(reinterpret_cast<const char*>(
pShaderBytecodeWithInputSignature), BytecodeLength);
DxbcModule dxbcModule(dxbcReader);
Rc<DxbcIsgn> inputSignature = dxbcModule.isgn();
std::vector<VkVertexInputAttributeDescription> attributes;
std::vector<VkVertexInputBindingDescription> bindings;
for (uint32_t i = 0; i < NumElements; i++) {
const DxbcSgnEntry* entry = inputSignature->find(
pInputElementDescs[i].SemanticName,
pInputElementDescs[i].SemanticIndex);
if (entry == nullptr) {
Logger::err(str::format(
"D3D11Device::CreateInputLayout: No such semantic: ",
pInputElementDescs[i].SemanticName,
pInputElementDescs[i].SemanticIndex));
return E_INVALIDARG;
}
// Create vertex input attribute description
VkVertexInputAttributeDescription attrib;
attrib.location = entry->registerId;
attrib.binding = pInputElementDescs[i].InputSlot;
attrib.format = m_dxgiAdapter->LookupFormat(
pInputElementDescs[i].Format).actual;
attrib.offset = pInputElementDescs[i].AlignedByteOffset;
if (attrib.offset == D3D11_APPEND_ALIGNED_ELEMENT) {
Logger::err("D3D11Device::CreateInputLayout: D3D11_APPEND_ALIGNED_ELEMENT not supported yet");
return E_INVALIDARG;
}
attributes.push_back(attrib);
// Create vertex input binding description.
VkVertexInputBindingDescription binding;
binding.binding = pInputElementDescs[i].InputSlot;
binding.stride = 0;
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
if (pInputElementDescs[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA) {
binding.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
if (pInputElementDescs[i].InstanceDataStepRate != 1) {
Logger::err(str::format(
"D3D11Device::CreateInputLayout: Unsupported instance data step rate: ",
pInputElementDescs[i].InstanceDataStepRate));
}
}
// Check if the binding was already defined. If so, the
// parameters must be identical (namely, the input rate).
bool bindingDefined = false;
for (const auto& existingBinding : bindings) {
if (binding.binding == existingBinding.binding) {
bindingDefined = true;
if (binding.inputRate != existingBinding.inputRate) {
Logger::err(str::format(
"D3D11Device::CreateInputLayout: Conflicting input rate for binding ",
binding.binding));
return E_INVALIDARG;
}
}
}
if (!bindingDefined)
bindings.push_back(binding);
}
// Create the actual input layout object
// if the application requests it.
if (ppInputLayout != nullptr) {
*ppInputLayout = ref(
new D3D11InputLayout(this,
new DxvkInputLayout(
attributes.size(),
attributes.data(),
bindings.size(),
bindings.data())));
}
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return E_INVALIDARG;
}
}

View File

@ -0,0 +1,33 @@
#include "d3d11_device.h"
#include "d3d11_input_layout.h"
namespace dxvk {
D3D11InputLayout::D3D11InputLayout(
D3D11Device* pDevice,
const Rc<DxvkInputLayout>& inputLayout)
: m_device(pDevice), m_inputLayout(inputLayout) {
}
D3D11InputLayout::~D3D11InputLayout() {
}
HRESULT D3D11InputLayout::QueryInterface(REFIID riid, void** ppvObject) {
COM_QUERY_IFACE(riid, ppvObject, IUnknown);
COM_QUERY_IFACE(riid, ppvObject, ID3D11DeviceChild);
COM_QUERY_IFACE(riid, ppvObject, ID3D11InputLayout);
Logger::warn("D3D11InputLayout::QueryInterface: Unknown interface query");
return E_NOINTERFACE;
}
void D3D11InputLayout::GetDevice(ID3D11Device** ppDevice) {
*ppDevice = ref(m_device);
}
}

View File

@ -0,0 +1,37 @@
#pragma once
#include "d3d11_device_child.h"
namespace dxvk {
class D3D11Device;
class D3D11InputLayout : public D3D11DeviceChild<ID3D11InputLayout> {
public:
D3D11InputLayout(
D3D11Device* pDevice,
const Rc<DxvkInputLayout>& inputLayout);
~D3D11InputLayout();
HRESULT QueryInterface(
REFIID riid,
void** ppvObject) final;
void GetDevice(
ID3D11Device **ppDevice) final;
Rc<DxvkInputLayout> GetDXVKInputLayout() const {
return m_inputLayout;
}
private:
D3D11Device* const m_device;
Rc<DxvkInputLayout> m_inputLayout;
};
}

View File

@ -3,6 +3,7 @@ d3d11_src = [
'd3d11_context.cpp',
'd3d11_device.cpp',
'd3d11_enums.cpp',
'd3d11_input_layout.cpp',
'd3d11_main.cpp',
'd3d11_present.cpp',
'd3d11_shader.cpp',

View File

@ -29,4 +29,17 @@ namespace dxvk {
}
const DxbcSgnEntry* DxbcIsgn::find(
const std::string& semanticName,
uint32_t semanticIndex) const {
for (auto e = this->begin(); e != this->end(); e++) {
if (e->semanticName == semanticName
&& e->semanticIndex == semanticIndex)
return &(*e);
}
return nullptr;
}
}

View File

@ -39,6 +39,10 @@ namespace dxvk {
auto begin() const { return m_entries.cbegin(); }
auto end () const { return m_entries.cend(); }
const DxbcSgnEntry* find(
const std::string& semanticName,
uint32_t semanticIndex) const;
private:
std::vector<DxbcSgnEntry> m_entries;

View File

@ -35,6 +35,15 @@ namespace dxvk {
return m_shexChunk->version();
}
/**
* \brief Input and output signature chunks
*
* Parts of the D3D11 API need access to the
* input or output signature of the shader.
*/
Rc<DxbcIsgn> isgn() const { return m_isgnChunk; }
Rc<DxbcIsgn> osgn() const { return m_osgnChunk; }
/**
* \brief Compiles DXBC shader to SPIR-V module
* \returns The compiled DXVK shader object