mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-30 20:52:11 +01:00
[dxbc] Added bound checking for some texel fetch operations
This commit is contained in:
parent
043330132f
commit
bfac9eb737
@ -656,18 +656,14 @@ namespace dxvk {
|
|||||||
|
|
||||||
// We do not know whether the image is going to be used as a color
|
// We do not know whether the image is going to be used as a color
|
||||||
// image or a depth image yet, so we'll declare types for both.
|
// image or a depth image yet, so we'll declare types for both.
|
||||||
const uint32_t colorTypeId = m_module.defImageType(sampledTypeId,
|
const uint32_t imageTypeId = m_module.defImageType(sampledTypeId,
|
||||||
typeInfo.dim, 0, typeInfo.array, typeInfo.ms, typeInfo.sampled,
|
typeInfo.dim, 2, typeInfo.array, typeInfo.ms, typeInfo.sampled,
|
||||||
spv::ImageFormatUnknown);
|
|
||||||
|
|
||||||
const uint32_t depthTypeId = m_module.defImageType(sampledTypeId,
|
|
||||||
typeInfo.dim, 1, typeInfo.array, typeInfo.ms, typeInfo.sampled,
|
|
||||||
spv::ImageFormatUnknown);
|
spv::ImageFormatUnknown);
|
||||||
|
|
||||||
// We'll declare the texture variable with the color type
|
// We'll declare the texture variable with the color type
|
||||||
// and decide which one to use when the texture is sampled.
|
// and decide which one to use when the texture is sampled.
|
||||||
const uint32_t resourcePtrType = m_module.defPointerType(
|
const uint32_t resourcePtrType = m_module.defPointerType(
|
||||||
colorTypeId, spv::StorageClassUniformConstant);
|
imageTypeId, spv::StorageClassUniformConstant);
|
||||||
|
|
||||||
const uint32_t varId = m_module.newVar(resourcePtrType,
|
const uint32_t varId = m_module.newVar(resourcePtrType,
|
||||||
spv::StorageClassUniformConstant);
|
spv::StorageClassUniformConstant);
|
||||||
@ -682,7 +678,7 @@ namespace dxvk {
|
|||||||
uav.varId = varId;
|
uav.varId = varId;
|
||||||
uav.sampledType = sampledType;
|
uav.sampledType = sampledType;
|
||||||
uav.sampledTypeId = sampledTypeId;
|
uav.sampledTypeId = sampledTypeId;
|
||||||
uav.imageTypeId = colorTypeId;
|
uav.imageTypeId = imageTypeId;
|
||||||
uav.structStride = 0;
|
uav.structStride = 0;
|
||||||
m_uavs.at(registerId) = uav;
|
m_uavs.at(registerId) = uav;
|
||||||
} else {
|
} else {
|
||||||
@ -692,10 +688,15 @@ namespace dxvk {
|
|||||||
res.varId = varId;
|
res.varId = varId;
|
||||||
res.sampledType = sampledType;
|
res.sampledType = sampledType;
|
||||||
res.sampledTypeId = sampledTypeId;
|
res.sampledTypeId = sampledTypeId;
|
||||||
res.colorTypeId = colorTypeId;
|
res.imageTypeId = imageTypeId;
|
||||||
res.depthTypeId = depthTypeId;
|
res.colorTypeId = m_module.defImageType(sampledTypeId,
|
||||||
|
typeInfo.dim, 0, typeInfo.array, typeInfo.ms, typeInfo.sampled,
|
||||||
|
spv::ImageFormatUnknown);
|
||||||
|
res.depthTypeId = m_module.defImageType(sampledTypeId,
|
||||||
|
typeInfo.dim, 1, typeInfo.array, typeInfo.ms, typeInfo.sampled,
|
||||||
|
spv::ImageFormatUnknown);
|
||||||
|
m_textures.at(registerId) = res;
|
||||||
res.structStride = 0;
|
res.structStride = 0;
|
||||||
m_textures.at(registerId) = res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the DXVK binding slot index for the resource.
|
// Compute the DXVK binding slot index for the resource.
|
||||||
@ -788,6 +789,7 @@ namespace dxvk {
|
|||||||
res.varId = varId;
|
res.varId = varId;
|
||||||
res.sampledType = sampledType;
|
res.sampledType = sampledType;
|
||||||
res.sampledTypeId = sampledTypeId;
|
res.sampledTypeId = sampledTypeId;
|
||||||
|
res.imageTypeId = resTypeId;
|
||||||
res.colorTypeId = resTypeId;
|
res.colorTypeId = resTypeId;
|
||||||
res.depthTypeId = resTypeId;
|
res.depthTypeId = resTypeId;
|
||||||
res.structStride = resStride;
|
res.structStride = resStride;
|
||||||
@ -1802,19 +1804,13 @@ namespace dxvk {
|
|||||||
// (src0) The buffer register to query
|
// (src0) The buffer register to query
|
||||||
const DxbcBufferInfo bufferInfo = getBufferInfo(ins.src[0]);
|
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
|
// We'll store this as a scalar unsigned integer
|
||||||
DxbcRegisterValue result;
|
DxbcRegisterValue result = emitQueryTexelBufferSize(ins.src[0]);
|
||||||
result.type.ctype = DxbcScalarType::Uint32;
|
|
||||||
result.type.ccount = 1;
|
|
||||||
|
|
||||||
const uint32_t typeId = getVectorTypeId(result.type);
|
const uint32_t typeId = getVectorTypeId(result.type);
|
||||||
result.id = m_module.opImageQuerySize(typeId, bufferId);
|
|
||||||
|
|
||||||
|
// Adjust returned size if this is a raw or structured
|
||||||
|
// buffer, as emitQueryTexelBufferSize only returns the
|
||||||
|
// number of typed elements in the buffer.
|
||||||
if (bufferInfo.type == DxbcResourceType::Raw) {
|
if (bufferInfo.type == DxbcResourceType::Raw) {
|
||||||
result.id = m_module.opIMul(typeId,
|
result.id = m_module.opIMul(typeId,
|
||||||
result.id, m_module.constu32(4));
|
result.id, m_module.constu32(4));
|
||||||
@ -1982,7 +1978,7 @@ namespace dxvk {
|
|||||||
// TODO support UAVs
|
// TODO support UAVs
|
||||||
const uint32_t textureId = ins.src[1].idx[0].offset;
|
const uint32_t textureId = ins.src[1].idx[0].offset;
|
||||||
const uint32_t imageId = m_module.opLoad(
|
const uint32_t imageId = m_module.opLoad(
|
||||||
m_textures.at(textureId).colorTypeId,
|
m_textures.at(textureId).imageTypeId,
|
||||||
m_textures.at(textureId).varId);
|
m_textures.at(textureId).varId);
|
||||||
|
|
||||||
// Read the exact LOD for the image query
|
// Read the exact LOD for the image query
|
||||||
@ -2104,24 +2100,15 @@ namespace dxvk {
|
|||||||
const uint32_t textureId = ins.src[1].idx[0].offset;
|
const uint32_t textureId = ins.src[1].idx[0].offset;
|
||||||
|
|
||||||
// Image type, which stores the image dimensions etc.
|
// Image type, which stores the image dimensions etc.
|
||||||
const DxbcImageInfo imageType = m_textures.at(textureId).imageInfo;
|
const DxbcImageInfo imageType = m_textures.at(textureId).imageInfo;
|
||||||
|
const DxbcRegMask coordArrayMask = getTexCoordMask(imageType);
|
||||||
|
|
||||||
const uint32_t imageLayerDim = [&] {
|
const uint32_t imageLayerDim = getTexLayerDim(imageType);
|
||||||
switch (imageType.dim) {
|
const uint32_t imageCoordDim = getTexCoordDim(imageType);
|
||||||
case spv::DimBuffer: return 1;
|
|
||||||
case spv::Dim1D: return 1;
|
|
||||||
case spv::Dim2D: return 2;
|
|
||||||
case spv::Dim3D: return 3;
|
|
||||||
default: throw DxvkError("DxbcCompiler: ld: Unsupported image dim");
|
|
||||||
}
|
|
||||||
}();
|
|
||||||
|
|
||||||
const DxbcRegMask coordArrayMask =
|
|
||||||
DxbcRegMask::firstN(imageLayerDim + imageType.array);
|
|
||||||
|
|
||||||
// Load the texture coordinates. The last component
|
// Load the texture coordinates. The last component
|
||||||
// contains the LOD if the resource is an image.
|
// contains the LOD if the resource is an image.
|
||||||
const DxbcRegisterValue coord = emitRegisterLoad(
|
const DxbcRegisterValue address = emitRegisterLoad(
|
||||||
ins.src[0], DxbcRegMask(true, true, true, true));
|
ins.src[0], DxbcRegMask(true, true, true, true));
|
||||||
|
|
||||||
// Additional image operands. This will store
|
// Additional image operands. This will store
|
||||||
@ -2141,16 +2128,41 @@ namespace dxvk {
|
|||||||
imageLayerDim, offsetIds.data());
|
imageLayerDim, offsetIds.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The LOD is not present when reading from a buffer
|
||||||
|
DxbcRegisterValue imageLod;
|
||||||
|
imageLod.type = address.type;
|
||||||
|
imageLod.id = 0;
|
||||||
|
|
||||||
if (imageType.dim != spv::DimBuffer) {
|
if (imageType.dim != spv::DimBuffer) {
|
||||||
|
imageLod = emitRegisterExtract(address,
|
||||||
|
DxbcRegMask(false, false, false, true));
|
||||||
|
|
||||||
imageOperands.flags |= spv::ImageOperandsLodMask;
|
imageOperands.flags |= spv::ImageOperandsLodMask;
|
||||||
imageOperands.sLod = emitRegisterExtract(coord,
|
imageOperands.sLod = imageLod.id;
|
||||||
DxbcRegMask(false, false, false, true)).id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load image variable, no sampler needed
|
// Extract coordinates from address
|
||||||
const uint32_t imageId = m_module.opLoad(
|
const DxbcRegisterValue coord = emitRegisterExtract(address, coordArrayMask);
|
||||||
m_textures.at(textureId).colorTypeId,
|
|
||||||
m_textures.at(textureId).varId);
|
// Perform bounds checking. If the coordinates are
|
||||||
|
// out of bounds, we return zero in all components.
|
||||||
|
const DxbcRegisterValue resourceSize = imageType.dim != spv::DimBuffer
|
||||||
|
? emitQueryTextureSize(ins.src[1], imageLod)
|
||||||
|
: emitQueryTexelBufferSize(ins.src[1]);
|
||||||
|
|
||||||
|
uint32_t boundCheckId = m_module.opULessThan(
|
||||||
|
m_module.defVectorType(m_module.defBoolType(), imageCoordDim),
|
||||||
|
coord.id, resourceSize.id);
|
||||||
|
|
||||||
|
if (imageCoordDim > 1)
|
||||||
|
boundCheckId = m_module.opAll(m_module.defBoolType(), boundCheckId);
|
||||||
|
|
||||||
|
const uint32_t boundCheckPassLabel = m_module.allocateId();
|
||||||
|
const uint32_t boundCheckFailLabel = m_module.allocateId();
|
||||||
|
const uint32_t boundCheckMergeLabel = m_module.allocateId();
|
||||||
|
|
||||||
|
m_module.opSelectionMerge(boundCheckMergeLabel, spv::SelectionControlMaskNone);
|
||||||
|
m_module.opBranchConditional(boundCheckId, boundCheckPassLabel, boundCheckFailLabel);
|
||||||
|
|
||||||
// Reading a typed image or buffer view
|
// Reading a typed image or buffer view
|
||||||
// always returns a four-component vector.
|
// always returns a four-component vector.
|
||||||
@ -2158,10 +2170,36 @@ namespace dxvk {
|
|||||||
result.type.ctype = m_textures.at(textureId).sampledType;
|
result.type.ctype = m_textures.at(textureId).sampledType;
|
||||||
result.type.ccount = 4;
|
result.type.ccount = 4;
|
||||||
|
|
||||||
result.id = m_module.opImageFetch(
|
// Bound check passed, load the texel
|
||||||
|
m_module.opLabel(boundCheckPassLabel);
|
||||||
|
|
||||||
|
const uint32_t imageId = m_module.opLoad(
|
||||||
|
m_textures.at(textureId).imageTypeId,
|
||||||
|
m_textures.at(textureId).varId);
|
||||||
|
|
||||||
|
const uint32_t boundCheckPassId = m_module.opImageFetch(
|
||||||
getVectorTypeId(result.type), imageId,
|
getVectorTypeId(result.type), imageId,
|
||||||
emitRegisterExtract(coord, coordArrayMask).id,
|
coord.id, imageOperands);
|
||||||
imageOperands);
|
|
||||||
|
m_module.opBranch(boundCheckMergeLabel);
|
||||||
|
m_module.opLabel (boundCheckFailLabel);
|
||||||
|
|
||||||
|
// Return zeroes if the bound check failed
|
||||||
|
const uint32_t boundCheckFailId = emitBuildZeroVec(result.type).id;
|
||||||
|
|
||||||
|
m_module.opBranch(boundCheckMergeLabel);
|
||||||
|
m_module.opLabel (boundCheckMergeLabel);
|
||||||
|
|
||||||
|
// Use a phi function to determine
|
||||||
|
// which of the results to take.
|
||||||
|
const std::array<SpirvPhiLabel, 2> phiOps = {{
|
||||||
|
{ boundCheckPassId, boundCheckPassLabel },
|
||||||
|
{ boundCheckFailId, boundCheckFailLabel },
|
||||||
|
}};
|
||||||
|
|
||||||
|
result.id = m_module.opPhi(
|
||||||
|
getVectorTypeId(result.type),
|
||||||
|
phiOps.size(), phiOps.data());
|
||||||
|
|
||||||
// Swizzle components using the texture swizzle
|
// Swizzle components using the texture swizzle
|
||||||
// and the destination operand's write mask
|
// and the destination operand's write mask
|
||||||
@ -2248,7 +2286,7 @@ namespace dxvk {
|
|||||||
const uint32_t sampledImageId = m_module.opSampledImage(
|
const uint32_t sampledImageId = m_module.opSampledImage(
|
||||||
sampledImageType,
|
sampledImageType,
|
||||||
m_module.opLoad(
|
m_module.opLoad(
|
||||||
m_textures.at(textureId).colorTypeId,
|
m_textures.at(textureId).imageTypeId,
|
||||||
m_textures.at(textureId).varId),
|
m_textures.at(textureId).varId),
|
||||||
m_module.opLoad(
|
m_module.opLoad(
|
||||||
m_samplers.at(samplerId).typeId,
|
m_samplers.at(samplerId).typeId,
|
||||||
@ -2798,6 +2836,43 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxbcRegisterValue DxbcCompiler::emitBuildZero(
|
||||||
|
DxbcScalarType type) {
|
||||||
|
DxbcRegisterValue result;
|
||||||
|
result.type.ctype = type;
|
||||||
|
result.type.ccount = 1;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case DxbcScalarType::Float32: result.id = m_module.constf32(0.0f); break;
|
||||||
|
case DxbcScalarType::Uint32: result.id = m_module.constu32(0); break;
|
||||||
|
case DxbcScalarType::Sint32: result.id = m_module.consti32(0); break;
|
||||||
|
default: throw DxvkError("DxbcCompiler: Invalid scalar type");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxbcRegisterValue DxbcCompiler::emitBuildZeroVec(
|
||||||
|
DxbcVectorType type) {
|
||||||
|
const DxbcRegisterValue scalar = emitBuildZero(type.ctype);
|
||||||
|
|
||||||
|
if (type.ccount == 1)
|
||||||
|
return scalar;
|
||||||
|
|
||||||
|
const std::array<uint32_t, 4> zeroIds = {{
|
||||||
|
scalar.id, scalar.id, scalar.id, scalar.id,
|
||||||
|
}};
|
||||||
|
|
||||||
|
DxbcRegisterValue result;
|
||||||
|
result.type = type;
|
||||||
|
result.id = m_module.constComposite(
|
||||||
|
getVectorTypeId(result.type),
|
||||||
|
zeroIds.size(), zeroIds.data());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DxbcRegisterValue DxbcCompiler::emitRegisterBitcast(
|
DxbcRegisterValue DxbcCompiler::emitRegisterBitcast(
|
||||||
DxbcRegisterValue srcValue,
|
DxbcRegisterValue srcValue,
|
||||||
DxbcScalarType dstType) {
|
DxbcScalarType dstType) {
|
||||||
@ -3412,6 +3487,55 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxbcRegisterValue DxbcCompiler::emitQueryTexelBufferSize(
|
||||||
|
const DxbcRegister& resource) {
|
||||||
|
// Load the texel buffer object. This cannot be used with
|
||||||
|
// constant buffers or any other type of resource.
|
||||||
|
const DxbcBufferInfo bufferInfo = getBufferInfo(resource);
|
||||||
|
|
||||||
|
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;
|
||||||
|
result.id = m_module.opImageQuerySize(
|
||||||
|
getVectorTypeId(result.type), bufferId);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxbcRegisterValue DxbcCompiler::emitQueryTextureLods(
|
||||||
|
const DxbcRegister& resource) {
|
||||||
|
const DxbcBufferInfo info = getBufferInfo(resource);
|
||||||
|
|
||||||
|
DxbcRegisterValue result;
|
||||||
|
result.type.ctype = DxbcScalarType::Uint32;
|
||||||
|
result.type.ccount = 1;
|
||||||
|
result.id = m_module.opImageQueryLevels(
|
||||||
|
getVectorTypeId(result.type),
|
||||||
|
m_module.opLoad(info.typeId, info.varId));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxbcRegisterValue DxbcCompiler::emitQueryTextureSize(
|
||||||
|
const DxbcRegister& resource,
|
||||||
|
DxbcRegisterValue lod) {
|
||||||
|
const DxbcBufferInfo info = getBufferInfo(resource);
|
||||||
|
|
||||||
|
DxbcRegisterValue result;
|
||||||
|
result.type.ctype = DxbcScalarType::Uint32;
|
||||||
|
result.type.ccount = getTexCoordDim(info.image);
|
||||||
|
result.id = m_module.opImageQuerySizeLod(
|
||||||
|
getVectorTypeId(result.type),
|
||||||
|
m_module.opLoad(info.typeId, info.varId),
|
||||||
|
lod.id);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DxbcRegisterValue DxbcCompiler::emitCalcBufferIndexStructured(
|
DxbcRegisterValue DxbcCompiler::emitCalcBufferIndexStructured(
|
||||||
DxbcRegisterValue structId,
|
DxbcRegisterValue structId,
|
||||||
DxbcRegisterValue structOffset,
|
DxbcRegisterValue structOffset,
|
||||||
@ -4124,8 +4248,9 @@ namespace dxvk {
|
|||||||
switch (reg.type) {
|
switch (reg.type) {
|
||||||
case DxbcOperandType::Resource: {
|
case DxbcOperandType::Resource: {
|
||||||
DxbcBufferInfo result;
|
DxbcBufferInfo result;
|
||||||
|
result.image = m_textures.at(registerId).imageInfo;
|
||||||
result.type = m_textures.at(registerId).type;
|
result.type = m_textures.at(registerId).type;
|
||||||
result.typeId = m_textures.at(registerId).colorTypeId;
|
result.typeId = m_textures.at(registerId).imageTypeId;
|
||||||
result.varId = m_textures.at(registerId).varId;
|
result.varId = m_textures.at(registerId).varId;
|
||||||
result.stride = m_textures.at(registerId).structStride;
|
result.stride = m_textures.at(registerId).structStride;
|
||||||
return result;
|
return result;
|
||||||
@ -4133,6 +4258,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
case DxbcOperandType::UnorderedAccessView: {
|
case DxbcOperandType::UnorderedAccessView: {
|
||||||
DxbcBufferInfo result;
|
DxbcBufferInfo result;
|
||||||
|
result.image = m_uavs.at(registerId).imageInfo;
|
||||||
result.type = m_uavs.at(registerId).type;
|
result.type = m_uavs.at(registerId).type;
|
||||||
result.typeId = m_uavs.at(registerId).imageTypeId;
|
result.typeId = m_uavs.at(registerId).imageTypeId;
|
||||||
result.varId = m_uavs.at(registerId).varId;
|
result.varId = m_uavs.at(registerId).varId;
|
||||||
@ -4142,6 +4268,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
case DxbcOperandType::ThreadGroupSharedMemory: {
|
case DxbcOperandType::ThreadGroupSharedMemory: {
|
||||||
DxbcBufferInfo result;
|
DxbcBufferInfo result;
|
||||||
|
result.image = { spv::DimBuffer, 0, 0, 0 };
|
||||||
result.type = m_gRegs.at(registerId).type;
|
result.type = m_gRegs.at(registerId).type;
|
||||||
result.typeId = m_module.defPointerType(
|
result.typeId = m_module.defPointerType(
|
||||||
getScalarTypeId(DxbcScalarType::Uint32),
|
getScalarTypeId(DxbcScalarType::Uint32),
|
||||||
@ -4157,19 +4284,24 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t DxbcCompiler::getTexLayerDim(const DxbcImageInfo& imageType) const {
|
||||||
|
switch (imageType.dim) {
|
||||||
|
case spv::DimBuffer: return 1;
|
||||||
|
case spv::Dim1D: return 1;
|
||||||
|
case spv::Dim2D: return 2;
|
||||||
|
case spv::Dim3D: return 3;
|
||||||
|
case spv::DimCube: return 3;
|
||||||
|
default: throw DxvkError("DxbcCompiler: getTexLayerDim: Unsupported image dimension");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DxbcCompiler::getTexCoordDim(const DxbcImageInfo& imageType) const {
|
||||||
|
return getTexLayerDim(imageType) + imageType.array;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DxbcRegMask DxbcCompiler::getTexCoordMask(const DxbcImageInfo& imageType) const {
|
DxbcRegMask DxbcCompiler::getTexCoordMask(const DxbcImageInfo& imageType) const {
|
||||||
const uint32_t imageLayerDim = [&] {
|
return DxbcRegMask::firstN(getTexCoordDim(imageType));
|
||||||
switch (imageType.dim) {
|
|
||||||
case spv::DimBuffer: return 1;
|
|
||||||
case spv::Dim1D: return 1;
|
|
||||||
case spv::Dim2D: return 2;
|
|
||||||
case spv::Dim3D: return 3;
|
|
||||||
case spv::DimCube: return 3;
|
|
||||||
default: throw DxvkError("DxbcCompiler: getTexCoordMask: Unsupported image dimension");
|
|
||||||
}
|
|
||||||
}();
|
|
||||||
|
|
||||||
return DxbcRegMask::firstN(imageLayerDim + imageType.array);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -193,6 +193,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
struct DxbcBufferInfo {
|
struct DxbcBufferInfo {
|
||||||
|
DxbcImageInfo image;
|
||||||
DxbcResourceType type;
|
DxbcResourceType type;
|
||||||
uint32_t typeId;
|
uint32_t typeId;
|
||||||
uint32_t varId;
|
uint32_t varId;
|
||||||
@ -497,6 +498,12 @@ namespace dxvk {
|
|||||||
const float values[4],
|
const float values[4],
|
||||||
const DxbcRegMask& writeMask);
|
const DxbcRegMask& writeMask);
|
||||||
|
|
||||||
|
DxbcRegisterValue emitBuildZero(
|
||||||
|
DxbcScalarType type);
|
||||||
|
|
||||||
|
DxbcRegisterValue emitBuildZeroVec(
|
||||||
|
DxbcVectorType type);
|
||||||
|
|
||||||
/////////////////////////////////////////
|
/////////////////////////////////////////
|
||||||
// Generic register manipulation methods
|
// Generic register manipulation methods
|
||||||
DxbcRegisterValue emitRegisterBitcast(
|
DxbcRegisterValue emitRegisterBitcast(
|
||||||
@ -578,6 +585,18 @@ namespace dxvk {
|
|||||||
DxbcRegisterValue elementIndex,
|
DxbcRegisterValue elementIndex,
|
||||||
DxbcRegisterValue value);
|
DxbcRegisterValue value);
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
// Resource query methods
|
||||||
|
DxbcRegisterValue emitQueryTexelBufferSize(
|
||||||
|
const DxbcRegister& resource);
|
||||||
|
|
||||||
|
DxbcRegisterValue emitQueryTextureLods(
|
||||||
|
const DxbcRegister& resource);
|
||||||
|
|
||||||
|
DxbcRegisterValue emitQueryTextureSize(
|
||||||
|
const DxbcRegister& resource,
|
||||||
|
DxbcRegisterValue lod);
|
||||||
|
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
// Buffer index calculation methods
|
// Buffer index calculation methods
|
||||||
DxbcRegisterValue emitCalcBufferIndexStructured(
|
DxbcRegisterValue emitCalcBufferIndexStructured(
|
||||||
@ -694,6 +713,12 @@ namespace dxvk {
|
|||||||
DxbcBufferInfo getBufferInfo(
|
DxbcBufferInfo getBufferInfo(
|
||||||
const DxbcRegister& reg);
|
const DxbcRegister& reg);
|
||||||
|
|
||||||
|
uint32_t getTexLayerDim(
|
||||||
|
const DxbcImageInfo& imageType) const;
|
||||||
|
|
||||||
|
uint32_t getTexCoordDim(
|
||||||
|
const DxbcImageInfo& imageType) const;
|
||||||
|
|
||||||
DxbcRegMask getTexCoordMask(
|
DxbcRegMask getTexCoordMask(
|
||||||
const DxbcImageInfo& imageType) const;
|
const DxbcImageInfo& imageType) const;
|
||||||
|
|
||||||
|
@ -74,6 +74,7 @@ namespace dxvk {
|
|||||||
uint32_t varId = 0;
|
uint32_t varId = 0;
|
||||||
DxbcScalarType sampledType = DxbcScalarType::Float32;
|
DxbcScalarType sampledType = DxbcScalarType::Float32;
|
||||||
uint32_t sampledTypeId = 0;
|
uint32_t sampledTypeId = 0;
|
||||||
|
uint32_t imageTypeId = 0;
|
||||||
uint32_t colorTypeId = 0;
|
uint32_t colorTypeId = 0;
|
||||||
uint32_t depthTypeId = 0;
|
uint32_t depthTypeId = 0;
|
||||||
uint32_t structStride = 0;
|
uint32_t structStride = 0;
|
||||||
|
@ -212,7 +212,7 @@ namespace dxvk {
|
|||||||
/* Ld */
|
/* Ld */
|
||||||
{ 3, DxbcInstClass::TextureFetch, {
|
{ 3, DxbcInstClass::TextureFetch, {
|
||||||
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
|
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
|
||||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 },
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
||||||
} },
|
} },
|
||||||
/* LdMs */
|
/* LdMs */
|
||||||
|
@ -591,6 +591,32 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::opAny(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t vector) {
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_code.putIns (spv::OpAny, 4);
|
||||||
|
m_code.putWord(resultType);
|
||||||
|
m_code.putWord(resultId);
|
||||||
|
m_code.putWord(vector);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::opAll(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t vector) {
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_code.putIns (spv::OpAll, 4);
|
||||||
|
m_code.putWord(resultType);
|
||||||
|
m_code.putWord(resultId);
|
||||||
|
m_code.putWord(vector);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvModule::opAtomicLoad(
|
uint32_t SpirvModule::opAtomicLoad(
|
||||||
uint32_t resultType,
|
uint32_t resultType,
|
||||||
uint32_t pointer,
|
uint32_t pointer,
|
||||||
@ -2409,6 +2435,25 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::opPhi(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t sourceCount,
|
||||||
|
const SpirvPhiLabel* sourceLabels) {
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_code.putIns (spv::OpPhi, 3 + 2 * sourceCount);
|
||||||
|
m_code.putWord(resultType);
|
||||||
|
m_code.putWord(resultId);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < sourceCount; i++) {
|
||||||
|
m_code.putWord(sourceLabels[i].varId);
|
||||||
|
m_code.putWord(sourceLabels[i].labelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SpirvModule::opReturn() {
|
void SpirvModule::opReturn() {
|
||||||
m_code.putIns (spv::OpReturn, 1);
|
m_code.putIns (spv::OpReturn, 1);
|
||||||
|
@ -4,6 +4,11 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
|
struct SpirvPhiLabel {
|
||||||
|
uint32_t varId = 0;
|
||||||
|
uint32_t labelId = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct SpirvSwitchCaseLabel {
|
struct SpirvSwitchCaseLabel {
|
||||||
uint32_t literal = 0;
|
uint32_t literal = 0;
|
||||||
uint32_t labelId = 0;
|
uint32_t labelId = 0;
|
||||||
@ -250,6 +255,14 @@ namespace dxvk {
|
|||||||
uint32_t indexCount,
|
uint32_t indexCount,
|
||||||
const uint32_t* indexArray);
|
const uint32_t* indexArray);
|
||||||
|
|
||||||
|
uint32_t opAny(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t vector);
|
||||||
|
|
||||||
|
uint32_t opAll(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t vector);
|
||||||
|
|
||||||
uint32_t opAtomicLoad(
|
uint32_t opAtomicLoad(
|
||||||
uint32_t resultType,
|
uint32_t resultType,
|
||||||
uint32_t pointer,
|
uint32_t pointer,
|
||||||
@ -851,7 +864,11 @@ namespace dxvk {
|
|||||||
uint32_t jumpDefault,
|
uint32_t jumpDefault,
|
||||||
uint32_t caseCount,
|
uint32_t caseCount,
|
||||||
const SpirvSwitchCaseLabel* caseLabels);
|
const SpirvSwitchCaseLabel* caseLabels);
|
||||||
|
|
||||||
|
uint32_t opPhi(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t sourceCount,
|
||||||
|
const SpirvPhiLabel* sourceLabels);
|
||||||
|
|
||||||
void opReturn();
|
void opReturn();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user