...
 
Commits (7)
......@@ -1105,7 +1105,7 @@ namespace dxvk {
EmitCs([cDstImageView = view->GetImageView()]
(DxvkContext* ctx) {
ctx->generateMipmaps(cDstImageView);
ctx->generateMipmaps(cDstImageView, VK_FILTER_LINEAR);
});
}
......
......@@ -359,6 +359,9 @@ namespace dxvk {
DWORD ExposedMipLevels() { return m_exposedMipLevels; }
void SetMipFilter(D3DTEXTUREFILTERTYPE filter) { m_mipFilter = filter; }
D3DTEXTUREFILTERTYPE GetMipFilter() const { return m_mipFilter; }
private:
D3D9DeviceEx* m_device;
......@@ -400,6 +403,8 @@ namespace dxvk {
bool m_needsMipGen = false;
D3DTEXTUREFILTERTYPE m_mipFilter = D3DTEXF_LINEAR;
/**
* \brief Mip level
* \returns Size of packed mip level in bytes
......
......@@ -4207,9 +4207,10 @@ namespace dxvk {
void D3D9DeviceEx::EmitGenerateMips(
D3D9CommonTexture* pResource) {
EmitCs([
cImageView = pResource->GetSampleView(false)
cImageView = pResource->GetSampleView(false),
cFilter = pResource->GetMipFilter()
] (DxvkContext* ctx) {
ctx->generateMipmaps(cImageView);
ctx->generateMipmaps(cImageView, DecodeFilter(cFilter));
});
}
......
......@@ -26,8 +26,7 @@ namespace dxvk {
D3DRESOURCETYPE ResourceType)
: D3D9Resource<Base...> ( pDevice )
, m_texture ( pDevice, pDesc, ResourceType )
, m_lod ( 0 )
, m_autogenFilter ( D3DTEXF_LINEAR ) {
, m_lod ( 0 ) {
const uint32_t arraySlices = m_texture.Desc()->ArraySize;
const uint32_t mipLevels = m_texture.Desc()->MipLevels;
......@@ -75,12 +74,15 @@ namespace dxvk {
}
HRESULT STDMETHODCALLTYPE SetAutoGenFilterType(D3DTEXTUREFILTERTYPE FilterType) final {
m_autogenFilter = FilterType;
if (unlikely(FilterType == D3DTEXF_NONE))
return D3DERR_INVALIDCALL;
m_texture.SetMipFilter(FilterType);
return D3D_OK;
}
D3DTEXTUREFILTERTYPE STDMETHODCALLTYPE GetAutoGenFilterType() final {
return m_autogenFilter;
return m_texture.GetMipFilter();
}
void STDMETHODCALLTYPE GenerateMipSubLevels() final {
......@@ -104,7 +106,6 @@ namespace dxvk {
D3D9CommonTexture m_texture;
DWORD m_lod;
D3DTEXTUREFILTERTYPE m_autogenFilter;
std::vector<SubresourceData> m_subresources;
......
......@@ -719,12 +719,12 @@ namespace dxvk {
break;
}
sampler.typeId = m_module.defImageType(
sampler.imageTypeId = m_module.defImageType(
m_module.defFloatType(32),
dimensionality, depth ? 1 : 0, 0, 0, 1,
spv::ImageFormatUnknown);
sampler.typeId = m_module.defSampledImageType(sampler.typeId);
sampler.typeId = m_module.defSampledImageType(sampler.imageTypeId);
sampler.varId = m_module.newVar(
m_module.defPointerType(
......@@ -2707,8 +2707,6 @@ void DxsoCompiler::emitControlFlowGenericLoop(
const uint32_t typeId = getVectorTypeId(result.type);
const uint32_t imageVarId = m_module.opLoad(sampler.typeId, sampler.varId);
SpirvImageOperands imageOperands;
if (m_programInfo.type() == DxsoProgramTypes::VertexShader) {
imageOperands.sLod = m_module.constf32(0.0f);
......@@ -2787,8 +2785,8 @@ void DxsoCompiler::emitControlFlowGenericLoop(
result.id = this->emitSample(
projDivider != 0,
typeId,
imageVarId,
texcoordVar.id,
sampler,
texcoordVar,
reference,
fetch4,
imageOperands);
......@@ -2799,8 +2797,8 @@ void DxsoCompiler::emitControlFlowGenericLoop(
uint32_t nonProjResult = this->emitSample(
0,
typeId,
imageVarId,
texcoordVar.id,
sampler,
texcoordVar,
reference,
fetch4,
imageOperands);
......@@ -3045,8 +3043,8 @@ void DxsoCompiler::emitControlFlowGenericLoop(
uint32_t DxsoCompiler::emitSample(
bool projected,
uint32_t resultType,
uint32_t sampledImage,
uint32_t coordinates,
DxsoSamplerInfo& samplerInfo,
DxsoRegisterValue coordinates,
uint32_t reference,
uint32_t fetch4,
const SpirvImageOperands& operands) {
......@@ -3055,35 +3053,37 @@ void DxsoCompiler::emitControlFlowGenericLoop(
(operands.flags & spv::ImageOperandsLodMask)
|| (operands.flags & spv::ImageOperandsGradMask);
const uint32_t sampledImage = m_module.opLoad(samplerInfo.typeId, samplerInfo.varId);
uint32_t val;
// No Fetch 4
if (projected) {
if (depthCompare) {
if (explicitLod)
val = m_module.opImageSampleProjDrefExplicitLod(resultType, sampledImage, coordinates, reference, operands);
val = m_module.opImageSampleProjDrefExplicitLod(resultType, sampledImage, coordinates.id, reference, operands);
else
val = m_module.opImageSampleProjDrefImplicitLod(resultType, sampledImage, coordinates, reference, operands);
val = m_module.opImageSampleProjDrefImplicitLod(resultType, sampledImage, coordinates.id, reference, operands);
}
else {
if (explicitLod)
val = m_module.opImageSampleProjExplicitLod(resultType, sampledImage, coordinates, operands);
val = m_module.opImageSampleProjExplicitLod(resultType, sampledImage, coordinates.id, operands);
else
val = m_module.opImageSampleProjImplicitLod(resultType, sampledImage, coordinates, operands);
val = m_module.opImageSampleProjImplicitLod(resultType, sampledImage, coordinates.id, operands);
}
}
else {
if (depthCompare) {
if (explicitLod)
val = m_module.opImageSampleDrefExplicitLod(resultType, sampledImage, coordinates, reference, operands);
val = m_module.opImageSampleDrefExplicitLod(resultType, sampledImage, coordinates.id, reference, operands);
else
val = m_module.opImageSampleDrefImplicitLod(resultType, sampledImage, coordinates, reference, operands);
val = m_module.opImageSampleDrefImplicitLod(resultType, sampledImage, coordinates.id, reference, operands);
}
else {
if (explicitLod)
val = m_module.opImageSampleExplicitLod(resultType, sampledImage, coordinates, operands);
val = m_module.opImageSampleExplicitLod(resultType, sampledImage, coordinates.id, operands);
else
val = m_module.opImageSampleImplicitLod(resultType, sampledImage, coordinates, operands);
val = m_module.opImageSampleImplicitLod(resultType, sampledImage, coordinates.id, operands);
}
}
......@@ -3094,7 +3094,33 @@ void DxsoCompiler::emitControlFlowGenericLoop(
fetch4Operands.flags &= ~spv::ImageOperandsGradMask;
fetch4Operands.flags &= ~spv::ImageOperandsBiasMask;
uint32_t fetch4Val = m_module.opImageGather(resultType, sampledImage, coordinates, m_module.consti32(0), fetch4Operands);
// Doesn't really work for cubes...
// D3D9 does support gather on 3D but we cannot :<
// Nothing probably relies on that though.
// If we come back to this ever, make sure to handle cube/3d differences.
if (samplerInfo.dimensions == 2) {
uint32_t image = m_module.opImage(samplerInfo.imageTypeId, sampledImage);
// Account for half texel offset...
// textureSize = 1.0f / float(2 * textureSize(sampler, 0))
DxsoRegisterValue textureSize;
textureSize.type = { DxsoScalarType::Sint32, samplerInfo.dimensions };
textureSize.id = m_module.opImageQuerySizeLod(getVectorTypeId(textureSize.type), image, m_module.consti32(0));
textureSize.id = m_module.opIMul(getVectorTypeId(textureSize.type), textureSize.id, m_module.constiReplicant(2, samplerInfo.dimensions));
textureSize.type = { DxsoScalarType::Float32, samplerInfo.dimensions };
textureSize.id = m_module.opConvertStoF(getVectorTypeId(textureSize.type), textureSize.id);
textureSize.id = m_module.opFDiv(getVectorTypeId(textureSize.type), m_module.constfReplicant(1.0f, samplerInfo.dimensions), textureSize.id);
// coord => same dimensions as texture size (no cube here !)
const std::array<uint32_t, 4> naturalIndices = { 0, 1, 2, 3 };
coordinates.type.ccount = samplerInfo.dimensions;
coordinates.id = m_module.opVectorShuffle(getVectorTypeId(coordinates.type), coordinates.id, coordinates.id, coordinates.type.ccount, naturalIndices.data());
// coord += textureSize;
coordinates.id = m_module.opFAdd(getVectorTypeId(coordinates.type), coordinates.id, textureSize.id);
}
uint32_t fetch4Val = m_module.opImageGather(resultType, sampledImage, coordinates.id, m_module.consti32(0), fetch4Operands);
// A R G B swizzle... Funny D3D9 order.
const std::array<uint32_t, 4> indices = { 3, 0, 1, 2 };
fetch4Val = m_module.opVectorShuffle(resultType, fetch4Val, fetch4Val, indices.size(), indices.data());
......
......@@ -103,6 +103,8 @@ namespace dxvk {
uint32_t varId = 0;
uint32_t typeId = 0;
uint32_t imageTypeId = 0;
};
enum DxsoSamplerType : uint32_t {
......@@ -640,8 +642,8 @@ namespace dxvk {
uint32_t emitSample(
bool projected,
uint32_t resultType,
uint32_t sampledImage,
uint32_t coordinates,
DxsoSamplerInfo& samplerInfo,
DxsoRegisterValue coordinates,
uint32_t reference,
uint32_t fetch4,
const SpirvImageOperands& operands);
......
......@@ -1427,7 +1427,8 @@ namespace dxvk {
void DxvkContext::generateMipmaps(
const Rc<DxvkImageView>& imageView) {
const Rc<DxvkImageView>& imageView,
VkFilter filter) {
if (imageView->info().numLevels <= 1)
return;
......@@ -1442,7 +1443,7 @@ namespace dxvk {
// Common descriptor set properties that we use to
// bind the source image view to the fragment shader
VkDescriptorImageInfo descriptorImage;
descriptorImage.sampler = m_common->metaBlit().getSampler(VK_FILTER_LINEAR);
descriptorImage.sampler = m_common->metaBlit().getSampler(filter);
descriptorImage.imageView = VK_NULL_HANDLE;
descriptorImage.imageLayout = imageView->imageInfo().layout;
......
......@@ -624,9 +624,11 @@ namespace dxvk {
* Uses blitting to generate lower mip levels from
* the top-most mip level passed to this method.
* \param [in] imageView The image to generate mips for
* \param [in] filter The filter to use for generation
*/
void generateMipmaps(
const Rc<DxvkImageView>& imageView);
const Rc<DxvkImageView>& imageView,
VkFilter filter);
/**
* \brief Initializes or invalidates an image
......
......@@ -396,6 +396,42 @@ namespace dxvk {
return this->constComposite(vectorTypeId, count, args.data());
}
uint32_t SpirvModule::constiReplicant(
int32_t replicant,
uint32_t count) {
uint32_t value = this->consti32(replicant);
std::array<uint32_t, 4> args = { value, value, value, value };
// Can't make a scalar composite.
if (count == 1)
return args[0];
uint32_t scalarTypeId = this->defIntType(32, 1);
uint32_t vectorTypeId = this->defVectorType(scalarTypeId, count);
return this->constComposite(vectorTypeId, count, args.data());
}
uint32_t SpirvModule::constuReplicant(
int32_t replicant,
uint32_t count) {
uint32_t value = this->constu32(replicant);
std::array<uint32_t, 4> args = { value, value, value, value };
// Can't make a scalar composite.
if (count == 1)
return args[0];
uint32_t scalarTypeId = this->defIntType(32, 0);
uint32_t vectorTypeId = this->defVectorType(scalarTypeId, count);
return this->constComposite(vectorTypeId, count, args.data());
}
uint32_t SpirvModule::constComposite(
......@@ -2969,6 +3005,19 @@ namespace dxvk {
m_code.putWord(offset);
return resultId;
}
uint32_t SpirvModule::opImage(
uint32_t resultType,
uint32_t sampledImage) {
uint32_t resultId = this->allocateId();
m_code.putIns(spv::OpImage, 4);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(sampledImage);
return resultId;
}
uint32_t SpirvModule::opImageRead(
......
......@@ -179,6 +179,14 @@ namespace dxvk {
uint32_t constbReplicant(
bool replicant,
uint32_t count);
uint32_t constiReplicant(
int32_t replicant,
uint32_t count);
uint32_t constuReplicant(
int32_t replicant,
uint32_t count);
uint32_t constComposite(
uint32_t typeId,
......@@ -1020,6 +1028,10 @@ namespace dxvk {
uint32_t resultType,
uint32_t interpolant,
uint32_t offset);
uint32_t opImage(
uint32_t resultType,
uint32_t sampledImage);
uint32_t opImageRead(
uint32_t resultType,
......