From b4493d90d890c47405e5e61de97d877e7edb2c33 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 10 Dec 2017 12:08:20 +0100 Subject: [PATCH] [dxbc] Initial support for sample instruction --- src/dxbc/dxbc_compiler.cpp | 30 ++++++++++++++ src/dxbc/dxbc_compiler.h | 3 ++ src/dxbc/gen/dxbc_gen_common.cpp | 71 +++++++++++++++++++++++--------- src/dxbc/gen/dxbc_gen_common.h | 16 ++++--- 4 files changed, 95 insertions(+), 25 deletions(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 9e916117..897b4fd0 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -65,6 +65,9 @@ namespace dxvk { case DxbcOpcode::Ret: return this->opRet(ins); + case DxbcOpcode::Sample: + return this->opSample(ins); + default: Logger::err(str::format( "DxbcCompiler::processInstruction: Unhandled opcode: ", @@ -275,6 +278,33 @@ namespace dxvk { } + void DxbcCompiler::opSample(const DxbcInstruction& ins) { + // TODO support address offset + // TODO support more sample ops + auto dstOp = ins.operand(0); + auto coordOp = ins.operand(dstOp.length()); + auto texture = ins.operand(dstOp.length() + coordOp.length()); + auto sampler = ins.operand(dstOp.length() + coordOp.length() + texture.length()); + + if ((texture.token().indexDimension() != 1) + || (sampler.token().indexDimension() != 1)) + throw DxvkError("DXBC: opSample: Invalid operand index dimensions"); + + uint32_t textureId = texture.index(0).immPart(); + uint32_t samplerId = sampler.index(0).immPart(); + + DxbcValue coord = this->loadOperand(coordOp, + DxbcComponentMask(true, true, true, true), + DxbcScalarType::Float32); + + DxbcComponentMask mask = this->getDstOperandMask(dstOp); + + DxbcValue value = m_gen->texSample(textureId, samplerId, coord); + value = this->selectOperandComponents(texture.token(), value, mask); + this->storeOperand(dstOp, value, mask); + } + + DxbcValue DxbcCompiler::getDynamicIndexValue(const DxbcOperandIndex& index) { DxbcValue immPart; DxbcValue relPart; diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index 0612d1fa..807c22e9 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -63,6 +63,9 @@ namespace dxvk { void opRet( const DxbcInstruction& ins); + void opSample( + const DxbcInstruction& ins); + DxbcValue getDynamicIndexValue( const DxbcOperandIndex& index); diff --git a/src/dxbc/gen/dxbc_gen_common.cpp b/src/dxbc/gen/dxbc_gen_common.cpp index acbbd3c1..0dfcdea8 100644 --- a/src/dxbc/gen/dxbc_gen_common.cpp +++ b/src/dxbc/gen/dxbc_gen_common.cpp @@ -93,7 +93,7 @@ namespace dxvk { case DxbcResourceReturnType::Uint: sampledTypeId = m_module.defIntType (32, 0); break; } - uint32_t resourceTypeId = 0; + uint32_t textureTypeId = 0; switch (resourceType) { default: @@ -102,50 +102,50 @@ namespace dxvk { resourceType)); case DxbcResourceDim::Texture1D: - resourceTypeId = m_module.defImageType( - sampledTypeId, spv::Dim1D, 2, 0, 0, 1, + textureTypeId = m_module.defImageType( + sampledTypeId, spv::Dim1D, 0, 0, 0, 1, spv::ImageFormatUnknown); break; case DxbcResourceDim::Texture1DArr: - resourceTypeId = m_module.defImageType( - sampledTypeId, spv::Dim1D, 2, 1, 0, 1, + textureTypeId = m_module.defImageType( + sampledTypeId, spv::Dim1D, 0, 1, 0, 1, spv::ImageFormatUnknown); break; case DxbcResourceDim::Texture2D: - resourceTypeId = m_module.defImageType( - sampledTypeId, spv::Dim2D, 2, 0, 0, 1, + textureTypeId = m_module.defImageType( + sampledTypeId, spv::Dim2D, 0, 0, 0, 1, spv::ImageFormatUnknown); break; case DxbcResourceDim::Texture2DArr: - resourceTypeId = m_module.defImageType( - sampledTypeId, spv::Dim2D, 2, 1, 0, 1, + textureTypeId = m_module.defImageType( + sampledTypeId, spv::Dim2D, 0, 1, 0, 1, spv::ImageFormatUnknown); break; case DxbcResourceDim::Texture3D: - resourceTypeId = m_module.defImageType( - sampledTypeId, spv::Dim3D, 2, 0, 0, 1, + textureTypeId = m_module.defImageType( + sampledTypeId, spv::Dim3D, 0, 0, 0, 1, spv::ImageFormatUnknown); break; case DxbcResourceDim::TextureCube: - resourceTypeId = m_module.defImageType( - sampledTypeId, spv::DimCube, 2, 0, 0, 1, + textureTypeId = m_module.defImageType( + sampledTypeId, spv::DimCube, 0, 0, 0, 1, spv::ImageFormatUnknown); break; case DxbcResourceDim::TextureCubeArr: - resourceTypeId = m_module.defImageType( - sampledTypeId, spv::DimCube, 2, 1, 0, 1, + textureTypeId = m_module.defImageType( + sampledTypeId, spv::DimCube, 0, 1, 0, 1, spv::ImageFormatUnknown); break; } uint32_t resourcePtrType = m_module.defPointerType( - resourceTypeId, spv::StorageClassUniformConstant); + textureTypeId, spv::StorageClassUniformConstant); uint32_t varId = m_module.newVar(resourcePtrType, spv::StorageClassUniformConstant); @@ -153,9 +153,9 @@ namespace dxvk { m_module.setDebugName(varId, str::format("t", registerId).c_str()); - m_resources.at(registerId).varId = varId; - m_resources.at(registerId).sampledTypeId = sampledTypeId; - m_resources.at(registerId).resourceTypeId = resourceTypeId; + m_textures.at(registerId).varId = varId; + m_textures.at(registerId).sampledTypeId = sampledTypeId; + m_textures.at(registerId).textureTypeId = textureTypeId; // Compute the DXVK binding slot index for the resource. // D3D11 needs to bind the actual resource to this slot. @@ -187,7 +187,8 @@ namespace dxvk { m_module.setDebugName(varId, str::format("s", samplerId).c_str()); - m_samplers.at(samplerId).varId = varId; + m_samplers.at(samplerId).varId = varId; + m_samplers.at(samplerId).typeId = samplerType; // Compute binding slot index for the sampler uint32_t bindingId = computeResourceSlotId(m_shaderStage, @@ -552,6 +553,36 @@ namespace dxvk { } + DxbcValue DxbcCodeGen::texSample( + const uint32_t textureId, + const uint32_t samplerId, + const DxbcValue& coordinates) { + // Combine the texture and the sampler into a sampled image + uint32_t sampledImageType = m_module.defSampledImageType( + m_textures.at(textureId).textureTypeId); + + uint32_t sampledImageId = m_module.opSampledImage( + sampledImageType, + m_module.opLoad( + m_textures.at(textureId).textureTypeId, + m_textures.at(textureId).varId), + m_module.opLoad( + m_samplers.at(samplerId).typeId, + m_samplers.at(samplerId).varId)); + + // Sampling an image in SPIR-V always returns a four-component + // vector, so we need to declare the corresponding type here + // TODO infer sampled type properly + DxbcValue result; + result.type = DxbcValueType(DxbcScalarType::Float32, 4); + result.valueId = m_module.opImageSampleImplicitLod( + this->defValueType(result.type), + sampledImageId, + this->regExtract(coordinates, DxbcComponentMask(true, true, false, false)).valueId); + return result; + } + + Rc DxbcCodeGen::create( const DxbcProgramVersion& version, const Rc& isgn, diff --git a/src/dxbc/gen/dxbc_gen_common.h b/src/dxbc/gen/dxbc_gen_common.h index ece6201f..ce6af4a5 100644 --- a/src/dxbc/gen/dxbc_gen_common.h +++ b/src/dxbc/gen/dxbc_gen_common.h @@ -41,7 +41,8 @@ namespace dxvk { * Stores a sampler variable. */ struct DxbcSampler { - uint32_t varId = 0; + uint32_t varId = 0; + uint32_t typeId = 0; }; @@ -51,9 +52,9 @@ namespace dxvk { * Stores the sampler variable as well as */ struct DxbcShaderResource { - uint32_t varId = 0; - uint32_t sampledTypeId = 0; - uint32_t resourceTypeId = 0; + uint32_t varId = 0; + uint32_t sampledTypeId = 0; + uint32_t textureTypeId = 0; }; @@ -149,6 +150,11 @@ namespace dxvk { const DxbcValue& val, DxbcComponentMask mask); + DxbcValue texSample( + const uint32_t textureId, + const uint32_t samplerId, + const DxbcValue& coordinates); + virtual void dclInterfaceVar( DxbcOperandType regType, uint32_t regId, @@ -191,7 +197,7 @@ namespace dxvk { std::array m_constantBuffers; std::array m_samplers; - std::array m_resources; + std::array m_textures; std::vector m_resourceSlots;