mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-01 16:24:12 +01:00
[dxbc] Fixed SV_VERTEXID and SV_INSTANCEID
Apparently, these two system values ignore the base vertex and base instance from the draw call. This is not documented, but in line with what the AMD driver does on Windows.
This commit is contained in:
parent
24b9d9d99a
commit
5ce975eed9
@ -2536,19 +2536,27 @@ namespace dxvk {
|
||||
DxbcRegMask mask) {
|
||||
switch (sv) {
|
||||
case DxbcSystemValue::VertexId: {
|
||||
DxbcRegisterPointer ptrIn;
|
||||
ptrIn.type.ctype = DxbcScalarType::Uint32;
|
||||
ptrIn.type.ccount = 1;
|
||||
ptrIn.id = m_vs.builtinVertexId;
|
||||
return emitValueLoad(ptrIn);
|
||||
const uint32_t typeId = getScalarTypeId(DxbcScalarType::Uint32);
|
||||
|
||||
DxbcRegisterValue result;
|
||||
result.type.ctype = DxbcScalarType::Uint32;
|
||||
result.type.ccount = 1;
|
||||
result.id = m_module.opISub(typeId,
|
||||
m_module.opLoad(typeId, m_vs.builtinVertexId),
|
||||
m_module.opLoad(typeId, m_vs.builtinBaseVertex));
|
||||
return result;
|
||||
} break;
|
||||
|
||||
case DxbcSystemValue::InstanceId: {
|
||||
DxbcRegisterPointer ptrIn;
|
||||
ptrIn.type.ctype = DxbcScalarType::Uint32;
|
||||
ptrIn.type.ccount = 1;
|
||||
ptrIn.id = m_vs.builtinInstanceId;
|
||||
return emitValueLoad(ptrIn);
|
||||
const uint32_t typeId = getScalarTypeId(DxbcScalarType::Uint32);
|
||||
|
||||
DxbcRegisterValue result;
|
||||
result.type.ctype = DxbcScalarType::Uint32;
|
||||
result.type.ccount = 1;
|
||||
result.id = m_module.opISub(typeId,
|
||||
m_module.opLoad(typeId, m_vs.builtinInstanceId),
|
||||
m_module.opLoad(typeId, m_vs.builtinBaseInstance));
|
||||
return result;
|
||||
} break;
|
||||
|
||||
default:
|
||||
@ -2663,14 +2671,26 @@ namespace dxvk {
|
||||
m_vs.builtinVertexId = emitNewBuiltinVariable({
|
||||
{ DxbcScalarType::Uint32, 1, 0 },
|
||||
spv::StorageClassInput },
|
||||
spv::BuiltInVertexId, // TODO test
|
||||
spv::BuiltInVertexIndex,
|
||||
"vs_vertex_index");
|
||||
|
||||
m_vs.builtinInstanceId = emitNewBuiltinVariable({
|
||||
{ DxbcScalarType::Uint32, 1, 0 },
|
||||
spv::StorageClassInput },
|
||||
spv::BuiltInInstanceId, // TODO test
|
||||
spv::BuiltInInstanceIndex, // TODO test
|
||||
"vs_instance_index");
|
||||
|
||||
m_vs.builtinBaseVertex = emitNewBuiltinVariable({
|
||||
{ DxbcScalarType::Uint32, 1, 0 },
|
||||
spv::StorageClassInput },
|
||||
spv::BuiltInBaseVertex,
|
||||
"vs_base_vertex");
|
||||
|
||||
m_vs.builtinBaseInstance = emitNewBuiltinVariable({
|
||||
{ DxbcScalarType::Uint32, 1, 0 },
|
||||
spv::StorageClassInput },
|
||||
spv::BuiltInBaseInstance,
|
||||
"vs_base_instance");
|
||||
}
|
||||
|
||||
|
||||
|
@ -92,8 +92,10 @@ namespace dxvk {
|
||||
struct DxbcCompilerVsPart {
|
||||
uint32_t functionId = 0;
|
||||
|
||||
uint32_t builtinVertexId = 0;
|
||||
uint32_t builtinInstanceId = 0;
|
||||
uint32_t builtinVertexId = 0;
|
||||
uint32_t builtinInstanceId = 0;
|
||||
uint32_t builtinBaseVertex = 0;
|
||||
uint32_t builtinBaseInstance = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -974,6 +974,21 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::opISub(
|
||||
uint32_t resultType,
|
||||
uint32_t a,
|
||||
uint32_t b) {
|
||||
uint32_t resultId = this->allocateId();
|
||||
|
||||
m_code.putIns (spv::OpISub, 5);
|
||||
m_code.putWord(resultType);
|
||||
m_code.putWord(resultId);
|
||||
m_code.putWord(a);
|
||||
m_code.putWord(b);
|
||||
return resultId;
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::opFAdd(
|
||||
uint32_t resultType,
|
||||
uint32_t a,
|
||||
@ -989,6 +1004,21 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::opFSub(
|
||||
uint32_t resultType,
|
||||
uint32_t a,
|
||||
uint32_t b) {
|
||||
uint32_t resultId = this->allocateId();
|
||||
|
||||
m_code.putIns (spv::OpFSub, 5);
|
||||
m_code.putWord(resultType);
|
||||
m_code.putWord(resultId);
|
||||
m_code.putWord(a);
|
||||
m_code.putWord(b);
|
||||
return resultId;
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::opSDiv(
|
||||
uint32_t resultType,
|
||||
uint32_t a,
|
||||
|
@ -354,11 +354,21 @@ namespace dxvk {
|
||||
uint32_t a,
|
||||
uint32_t b);
|
||||
|
||||
uint32_t opISub(
|
||||
uint32_t resultType,
|
||||
uint32_t a,
|
||||
uint32_t b);
|
||||
|
||||
uint32_t opFAdd(
|
||||
uint32_t resultType,
|
||||
uint32_t a,
|
||||
uint32_t b);
|
||||
|
||||
uint32_t opFSub(
|
||||
uint32_t resultType,
|
||||
uint32_t a,
|
||||
uint32_t b);
|
||||
|
||||
uint32_t opSDiv(
|
||||
uint32_t resultType,
|
||||
uint32_t a,
|
||||
|
@ -19,25 +19,28 @@ struct Vertex {
|
||||
const std::string g_vertexShaderCode =
|
||||
"struct vs_out {\n"
|
||||
" float4 pos : SV_POSITION;\n"
|
||||
" float2 coord : COORD;\n"
|
||||
" uint vid : VID;\n"
|
||||
" uint iid : IID;\n"
|
||||
"};\n"
|
||||
"vs_out main(float4 vsIn : IN_POSITION) {\n"
|
||||
"vs_out main(float4 vsIn : IN_POSITION,\n"
|
||||
" uint vid : SV_VERTEXID,\n"
|
||||
" uint iid : SV_INSTANCEID) {\n"
|
||||
" vs_out result;\n"
|
||||
" result.pos = vsIn;\n"
|
||||
" result.coord = result.pos.xy;\n"
|
||||
" result.vid = vid;\n"
|
||||
" result.iid = iid;\n"
|
||||
" return result;\n"
|
||||
"}\n";
|
||||
|
||||
const std::string g_pixelShaderCode =
|
||||
"struct vs_out {\n"
|
||||
" float4 pos : SV_POSITION;\n"
|
||||
" float2 coord : COORD;\n"
|
||||
" uint vid : VID;\n"
|
||||
" uint iid : IID;\n"
|
||||
"};\n"
|
||||
"Texture1D t : register(t0);\n"
|
||||
"sampler s : register(s0);\n"
|
||||
"cbuffer c_buffer { float4 ccolor[2]; };\n"
|
||||
"float4 main(vs_out ps_in) : SV_TARGET {\n"
|
||||
" return ccolor[0] * t.Sample(s, 0.5f + 0.5f * ps_in.coord.y);\n"
|
||||
" return 0.5f * (ccolor[min(ps_in.vid, 1u)] + ccolor[min(ps_in.iid, 1u)]);\n"
|
||||
"}\n";
|
||||
|
||||
class TriangleApp {
|
||||
@ -73,7 +76,7 @@ public:
|
||||
swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
swapDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||
swapDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
swapDesc.SampleDesc.Count = 1;
|
||||
swapDesc.SampleDesc.Count = 8;
|
||||
swapDesc.SampleDesc.Quality = 0;
|
||||
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapDesc.BufferCount = 2;
|
||||
@ -94,10 +97,28 @@ public:
|
||||
if (FAILED(m_swapChain->ResizeTarget(&swapDesc.BufferDesc)))
|
||||
throw DxvkError("Failed to resize window");
|
||||
|
||||
std::array<Vertex, 3> vertexData = {{
|
||||
{ -0.5f, -0.5f, 0.0f, 1.0f },
|
||||
{ 0.0f, 0.5f, 0.0f, 1.0f },
|
||||
{ 0.5f, -0.5f, 0.0f, 1.0f },
|
||||
std::array<Vertex, 21> vertexData = {{
|
||||
{ -0.25f, -0.15f, 0.0f, 1.0f },
|
||||
{ -0.50f, -0.65f, 0.0f, 1.0f },
|
||||
{ -0.75f, -0.15f, 0.0f, 1.0f },
|
||||
{ 0.75f, -0.15f, 0.0f, 1.0f },
|
||||
{ 0.50f, -0.65f, 0.0f, 1.0f },
|
||||
{ 0.25f, -0.15f, 0.0f, 1.0f },
|
||||
{ -0.75f, 0.15f, 0.0f, 1.0f },
|
||||
{ -0.50f, 0.65f, 0.0f, 1.0f },
|
||||
{ -0.25f, 0.15f, 0.0f, 1.0f },
|
||||
{ 0.25f, 0.15f, 0.0f, 1.0f },
|
||||
{ 0.50f, 0.65f, 0.0f, 1.0f },
|
||||
{ 0.75f, 0.15f, 0.0f, 1.0f },
|
||||
{ 0.25f, 0.75f, 0.0f, 1.0f },
|
||||
{ 0.00f, 0.25f, 0.0f, 1.0f },
|
||||
{ -0.25f, 0.75f, 0.0f, 1.0f },
|
||||
{ -0.25f, -0.75f, 0.0f, 1.0f },
|
||||
{ 0.00f, -0.25f, 0.0f, 1.0f },
|
||||
{ 0.25f, -0.75f, 0.0f, 1.0f },
|
||||
{ -0.25f, -0.25f, 0.0f, 1.0f },
|
||||
{ 0.00f, 0.25f, 0.0f, 1.0f },
|
||||
{ 0.25f, -0.25f, 0.0f, 1.0f },
|
||||
}};
|
||||
|
||||
D3D11_BUFFER_DESC vertexDesc;
|
||||
@ -116,9 +137,29 @@ public:
|
||||
if (FAILED(m_device->CreateBuffer(&vertexDesc, &vertexDataInfo, &m_vertexBuffer)))
|
||||
throw DxvkError("Failed to create vertex buffer");
|
||||
|
||||
std::array<uint32_t, 9> indexData = {{
|
||||
0, 1, 2, 0, 1, 2, 2, 1, 0
|
||||
}};
|
||||
|
||||
D3D11_BUFFER_DESC indexDesc;
|
||||
indexDesc.ByteWidth = sizeof(uint32_t) * indexData.size();
|
||||
indexDesc.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
indexDesc.CPUAccessFlags = 0;
|
||||
indexDesc.MiscFlags = 0;
|
||||
indexDesc.StructureByteStride = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA indexDataInfo;
|
||||
indexDataInfo.pSysMem = indexData.data();
|
||||
indexDataInfo.SysMemPitch = 0;
|
||||
indexDataInfo.SysMemSlicePitch = 0;
|
||||
|
||||
if (FAILED(m_device->CreateBuffer(&indexDesc, &indexDataInfo, &m_indexBuffer)))
|
||||
throw DxvkError("Failed to create index buffer");
|
||||
|
||||
std::array<Vertex, 2> constantData = {{
|
||||
{ 0.03f, 0.03f, 0.03f, 1.0f },
|
||||
{ 1.00f, 1.00f, 1.00f, 1.0f },
|
||||
{ 1.00f, 0.00f, 0.00f, 1.0f },
|
||||
}};
|
||||
|
||||
D3D11_BUFFER_DESC constantDesc;
|
||||
@ -184,58 +225,6 @@ public:
|
||||
&m_vertexFormat)))
|
||||
throw DxvkError("Failed to create input layout");
|
||||
|
||||
D3D11_SAMPLER_DESC samplerDesc;
|
||||
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.MipLODBias = 0.0f;
|
||||
samplerDesc.MaxAnisotropy = 1.0f;
|
||||
samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
samplerDesc.BorderColor[0] = 0.0f;
|
||||
samplerDesc.BorderColor[1] = 0.0f;
|
||||
samplerDesc.BorderColor[2] = 0.0f;
|
||||
samplerDesc.BorderColor[3] = 0.0f;
|
||||
samplerDesc.MinLOD = 0.0f;
|
||||
samplerDesc.MaxLOD = 0.0f;
|
||||
|
||||
if (FAILED(m_device->CreateSamplerState(
|
||||
&samplerDesc,
|
||||
&m_sampler)))
|
||||
throw DxvkError("Failed to create sampler");
|
||||
|
||||
D3D11_TEXTURE1D_DESC colorBufferDesc;
|
||||
colorBufferDesc.Width = 4;
|
||||
colorBufferDesc.MipLevels = 1;
|
||||
colorBufferDesc.ArraySize = 1;
|
||||
colorBufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
colorBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
colorBufferDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
colorBufferDesc.CPUAccessFlags = 0;
|
||||
colorBufferDesc.MiscFlags = 0;
|
||||
|
||||
const std::array<uint8_t, 16> colorBufferContents = {
|
||||
0x00, 0x00, 0x00, 0xFF,
|
||||
0x80, 0x00, 0x00, 0xFF,
|
||||
0x80, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
};
|
||||
|
||||
D3D11_SUBRESOURCE_DATA colorBufferData;
|
||||
colorBufferData.pSysMem = colorBufferContents.data();
|
||||
colorBufferData.SysMemPitch = 0;
|
||||
colorBufferData.SysMemSlicePitch = 0;
|
||||
|
||||
if (FAILED(m_device->CreateTexture1D(
|
||||
&colorBufferDesc,
|
||||
&colorBufferData,
|
||||
&m_colorBuffer)))
|
||||
throw DxvkError("Failed to create 1D texture");
|
||||
|
||||
if (FAILED(m_device->CreateShaderResourceView(
|
||||
m_colorBuffer.ptr(), nullptr, &m_colorBufferSrv)))
|
||||
throw DxvkError("Failed to create 1D texture view");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -263,16 +252,35 @@ public:
|
||||
m_context->VSSetShader(m_vertexShader.ptr(), nullptr, 0);
|
||||
m_context->PSSetShader(m_pixelShader.ptr(), nullptr, 0);
|
||||
m_context->PSSetConstantBuffers(0, 1, &m_constantBuffer);
|
||||
m_context->PSSetShaderResources(0, 1, &m_colorBufferSrv);
|
||||
m_context->PSSetSamplers(0, 1, &m_sampler);
|
||||
|
||||
UINT vsStride = sizeof(Vertex);
|
||||
UINT vsOffset = 0;
|
||||
|
||||
// Test normal draws with base vertex
|
||||
m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
m_context->IASetInputLayout(m_vertexFormat.ptr());
|
||||
m_context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &vsStride, &vsOffset);
|
||||
m_context->Draw(3, 0);
|
||||
m_context->Draw(3, 3);
|
||||
|
||||
// Test instanced draws with base instance and base vertex
|
||||
vsOffset = 6 * sizeof(Vertex);
|
||||
m_context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &vsStride, &vsOffset);
|
||||
m_context->DrawInstanced(3, 1, 0, 1);
|
||||
m_context->DrawInstanced(3, 1, 3, 1);
|
||||
|
||||
// Test indexed draws with base vertex and base index
|
||||
vsOffset = 12 * sizeof(Vertex);
|
||||
m_context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &vsStride, &vsOffset);
|
||||
m_context->IASetIndexBuffer(m_indexBuffer.ptr(), DXGI_FORMAT_R32_UINT, 0);
|
||||
m_context->DrawIndexed(3, 0, 0);
|
||||
m_context->DrawIndexed(3, 3, 3);
|
||||
|
||||
// Test default backface culling
|
||||
vsOffset = 18 * sizeof(Vertex);
|
||||
m_context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &vsStride, &vsOffset);
|
||||
m_context->DrawIndexed(3, 6, 0);
|
||||
|
||||
m_context->OMSetRenderTargets(0, nullptr, nullptr);
|
||||
|
||||
m_swapChain->Present(0, 0);
|
||||
@ -320,13 +328,10 @@ private:
|
||||
Com<ID3D11Texture2D> m_buffer;
|
||||
Com<ID3D11RenderTargetView> m_bufferView;
|
||||
Com<ID3D11Buffer> m_constantBuffer;
|
||||
Com<ID3D11Buffer> m_indexBuffer;
|
||||
Com<ID3D11Buffer> m_vertexBuffer;
|
||||
Com<ID3D11InputLayout> m_vertexFormat;
|
||||
|
||||
Com<ID3D11SamplerState> m_sampler;
|
||||
Com<ID3D11Texture1D> m_colorBuffer;
|
||||
Com<ID3D11ShaderResourceView> m_colorBufferSrv;
|
||||
|
||||
Com<ID3D11VertexShader> m_vertexShader;
|
||||
Com<ID3D11PixelShader> m_pixelShader;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user