diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index a7c0448dd..419a758e6 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -72,6 +72,9 @@ namespace dxvk { case DxbcInstClass::Barrier: return this->emitBarrier(ins); + case DxbcInstClass::BufferQuery: + return this->emitBufferQuery(ins); + case DxbcInstClass::BufferLoad: return this->emitBufferLoad(ins); @@ -1588,6 +1591,40 @@ namespace dxvk { } + void DxbcCompiler::emitBufferQuery(const DxbcShaderInstruction& ins) { + // bufinfo takes two arguments + // (dst0) The destination register + // (src0) The buffer register to query + const DxbcBufferInfo bufferInfo = getBufferInfo(ins.src[0]); + + // This instruction can only be used with t# and u# + // registers, which are all mapped to texel buffers + const uint32_t bufferId = m_module.opLoad( + bufferInfo.typeId, bufferInfo.varId); + + // We'll store this as a scalar unsigned integer + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = 1; + + const uint32_t typeId = getVectorTypeId(result.type); + result.id = m_module.opImageQuerySize(typeId, bufferId); + + if (bufferInfo.type == DxbcResourceType::Raw) { + result.id = m_module.opIMul(typeId, + result.id, m_module.constu32(4)); + } else if (bufferInfo.type == DxbcResourceType::Structured) { + result.id = m_module.opUDiv(typeId, result.id, + m_module.constu32(bufferInfo.stride / 4)); + } + + // Store the result. The scalar will be extended to a + // vector if the write mask consists of more than one + // component, which is the desired behaviour. + emitRegisterStore(ins.dst[0], result); + } + + void DxbcCompiler::emitBufferLoad(const DxbcShaderInstruction& ins) { // ld_raw takes three arguments: // (dst0) Destination register diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index 347c7a2be..dce7f741f 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -395,6 +395,9 @@ namespace dxvk { void emitBarrier( const DxbcShaderInstruction& ins); + void emitBufferQuery( + const DxbcShaderInstruction& ins); + void emitBufferLoad( const DxbcShaderInstruction& ins); diff --git a/src/dxbc/dxbc_defs.cpp b/src/dxbc/dxbc_defs.cpp index 1b20c2253..87a06ab18 100644 --- a/src/dxbc/dxbc_defs.cpp +++ b/src/dxbc/dxbc_defs.cpp @@ -550,7 +550,10 @@ namespace dxvk { /* InterfaceCall */ { }, /* BufInfo */ - { }, + { 2, DxbcInstClass::BufferQuery, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, /* DerivRtxCoarse */ { 2, DxbcInstClass::VectorDeriv, { { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, diff --git a/src/dxbc/dxbc_defs.h b/src/dxbc/dxbc_defs.h index eb14643b2..81a2600f2 100644 --- a/src/dxbc/dxbc_defs.h +++ b/src/dxbc/dxbc_defs.h @@ -34,6 +34,7 @@ namespace dxvk { GeometryEmit, ///< Special geometry shader instructions Atomic, ///< Atomic operations Barrier, ///< Execution or memory barrier + BufferQuery, ///< Buffer query instruction BufferLoad, ///< Structured or raw buffer load BufferStore, ///< Structured or raw buffer store TextureQuery, ///< Texture query instruction diff --git a/src/dxgi/dxgi_adapter.cpp b/src/dxgi/dxgi_adapter.cpp index 92672dff3..b31d1e5d0 100644 --- a/src/dxgi/dxgi_adapter.cpp +++ b/src/dxgi/dxgi_adapter.cpp @@ -274,7 +274,9 @@ namespace dxvk { AddColorFormat(DXGI_FORMAT_R8_SNORM, VK_FORMAT_R8_SNORM); AddColorFormat(DXGI_FORMAT_R8_SINT, VK_FORMAT_R8_SINT); -// AddColorFormat(DXGI_FORMAT_A8_UNORM, VK_FORMAT_UNDEFINED); + AddColorFormat(DXGI_FORMAT_A8_UNORM, VK_FORMAT_R8_UNORM, + { VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ONE, + VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_R }); // AddColorFormat(DXGI_FORMAT_R1_UNORM, VK_FORMAT_UNDEFINED);