[D3D12] DXBC texture bindings (but no samplers and fetch)
This commit is contained in:
parent
091d51f841
commit
4268466383
|
@ -27,18 +27,20 @@ D3D12Shader::~D3D12Shader() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void D3D12Shader::SetTexturesAndSamplers(
|
void D3D12Shader::SetTexturesAndSamplers(
|
||||||
const HlslShaderTranslator::TextureSRV* texture_srvs,
|
const DxbcShaderTranslator::TextureSRV* texture_srvs,
|
||||||
uint32_t texture_srv_count, const uint32_t* sampler_fetch_constants,
|
uint32_t texture_srv_count, const uint32_t* sampler_fetch_constants,
|
||||||
uint32_t sampler_count) {
|
uint32_t sampler_count) {
|
||||||
|
used_texture_mask_ = 0;
|
||||||
for (uint32_t i = 0; i < texture_srv_count; ++i) {
|
for (uint32_t i = 0; i < texture_srv_count; ++i) {
|
||||||
TextureSRV& srv = texture_srvs_[i];
|
TextureSRV& srv = texture_srvs_[i];
|
||||||
const HlslShaderTranslator::TextureSRV& translator_srv = texture_srvs[i];
|
const DxbcShaderTranslator::TextureSRV& translator_srv = texture_srvs[i];
|
||||||
srv.fetch_constant = translator_srv.fetch_constant;
|
srv.fetch_constant = translator_srv.fetch_constant;
|
||||||
srv.dimension = translator_srv.dimension;
|
srv.dimension = translator_srv.dimension;
|
||||||
|
used_texture_mask_ |= 1u << translator_srv.fetch_constant;
|
||||||
}
|
}
|
||||||
texture_srv_count_ = texture_srv_count;
|
texture_srv_count_ = texture_srv_count;
|
||||||
|
#if 0
|
||||||
// If there's a texture, there's a sampler for it.
|
// If there's a texture, there's a sampler for it.
|
||||||
used_texture_mask_ = 0;
|
used_texture_mask_ = 0;
|
||||||
for (uint32_t i = 0; i < sampler_count; ++i) {
|
for (uint32_t i = 0; i < sampler_count; ++i) {
|
||||||
|
@ -47,8 +49,8 @@ void D3D12Shader::SetTexturesAndSamplers(
|
||||||
used_texture_mask_ |= 1u << sampler_fetch_constant;
|
used_texture_mask_ |= 1u << sampler_fetch_constant;
|
||||||
}
|
}
|
||||||
sampler_count_ = sampler_count;
|
sampler_count_ = sampler_count;
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool D3D12Shader::DisassembleDXBC() {
|
bool D3D12Shader::DisassembleDXBC() {
|
||||||
if (!host_disassembly_.empty()) {
|
if (!host_disassembly_.empty()) {
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
#ifndef XENIA_GPU_D3D12_D3D12_SHADER_H_
|
#ifndef XENIA_GPU_D3D12_D3D12_SHADER_H_
|
||||||
#define XENIA_GPU_D3D12_D3D12_SHADER_H_
|
#define XENIA_GPU_D3D12_D3D12_SHADER_H_
|
||||||
|
|
||||||
// TODO(Triang3l): Remove hlsl_shader_translator.
|
#include "xenia/gpu/dxbc_shader_translator.h"
|
||||||
#include "xenia/gpu/hlsl_shader_translator.h"
|
|
||||||
#include "xenia/gpu/shader.h"
|
#include "xenia/gpu/shader.h"
|
||||||
#include "xenia/ui/d3d12/d3d12_api.h"
|
#include "xenia/ui/d3d12/d3d12_api.h"
|
||||||
|
|
||||||
|
@ -25,12 +24,10 @@ class D3D12Shader : public Shader {
|
||||||
const uint32_t* dword_ptr, uint32_t dword_count);
|
const uint32_t* dword_ptr, uint32_t dword_count);
|
||||||
~D3D12Shader() override;
|
~D3D12Shader() override;
|
||||||
|
|
||||||
#if 0
|
|
||||||
void SetTexturesAndSamplers(
|
void SetTexturesAndSamplers(
|
||||||
const HlslShaderTranslator::TextureSRV* texture_srvs,
|
const DxbcShaderTranslator::TextureSRV* texture_srvs,
|
||||||
uint32_t texture_srv_count, const uint32_t* sampler_fetch_constants,
|
uint32_t texture_srv_count, const uint32_t* sampler_fetch_constants,
|
||||||
uint32_t sampler_count);
|
uint32_t sampler_count);
|
||||||
#endif
|
|
||||||
|
|
||||||
bool DisassembleDXBC();
|
bool DisassembleDXBC();
|
||||||
|
|
||||||
|
|
|
@ -198,15 +198,15 @@ bool PipelineCache::TranslateShader(D3D12Shader* shader,
|
||||||
|
|
||||||
// TODO(Triang3l): Re-enable this when the DXBC shader translators supports
|
// TODO(Triang3l): Re-enable this when the DXBC shader translators supports
|
||||||
// textures.
|
// textures.
|
||||||
#if 0
|
uint32_t texture_srv_count;
|
||||||
uint32_t texture_srv_count, sampler_count;
|
const DxbcShaderTranslator::TextureSRV* texture_srvs =
|
||||||
const HlslShaderTranslator::TextureSRV* texture_srvs =
|
|
||||||
shader_translator_->GetTextureSRVs(texture_srv_count);
|
shader_translator_->GetTextureSRVs(texture_srv_count);
|
||||||
|
#if 0
|
||||||
|
uint32_t sampler_count;
|
||||||
const uint32_t* sampler_fetch_constants =
|
const uint32_t* sampler_fetch_constants =
|
||||||
shader_translator_->GetSamplerFetchConstants(sampler_count);
|
shader_translator_->GetSamplerFetchConstants(sampler_count);
|
||||||
shader->SetTexturesAndSamplers(texture_srvs, texture_srv_count,
|
|
||||||
sampler_fetch_constants, sampler_count);
|
|
||||||
#endif
|
#endif
|
||||||
|
shader->SetTexturesAndSamplers(texture_srvs, texture_srv_count, nullptr, 0);
|
||||||
|
|
||||||
if (shader->is_valid()) {
|
if (shader->is_valid()) {
|
||||||
XELOGGPU("Generated %s shader (%db) - hash %.16" PRIX64 ":\n%s\n",
|
XELOGGPU("Generated %s shader (%db) - hash %.16" PRIX64 ":\n%s\n",
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "xenia/base/assert.h"
|
#include "xenia/base/assert.h"
|
||||||
#include "xenia/base/math.h"
|
#include "xenia/base/math.h"
|
||||||
|
#include "xenia/base/string.h"
|
||||||
|
|
||||||
DEFINE_bool(dxbc_indexable_temps, true,
|
DEFINE_bool(dxbc_indexable_temps, true,
|
||||||
"Use indexable temporary registers in translated DXBC shaders for "
|
"Use indexable temporary registers in translated DXBC shaders for "
|
||||||
|
@ -69,6 +70,8 @@ void DxbcShaderTranslator::Reset() {
|
||||||
system_temp_count_current_ = 0;
|
system_temp_count_current_ = 0;
|
||||||
system_temp_count_max_ = 0;
|
system_temp_count_max_ = 0;
|
||||||
writes_depth_ = false;
|
writes_depth_ = false;
|
||||||
|
texture_srvs_.clear();
|
||||||
|
sampler_bindings_.clear();
|
||||||
|
|
||||||
std::memset(&stat_, 0, sizeof(stat_));
|
std::memset(&stat_, 0, sizeof(stat_));
|
||||||
}
|
}
|
||||||
|
@ -474,6 +477,8 @@ void DxbcShaderTranslator::StartTranslation() {
|
||||||
system_temp_ps_pc_p0_a0_ = PushSystemTemp(true);
|
system_temp_ps_pc_p0_a0_ = PushSystemTemp(true);
|
||||||
system_temp_aL_ = PushSystemTemp(true);
|
system_temp_aL_ = PushSystemTemp(true);
|
||||||
system_temp_loop_count_ = PushSystemTemp(true);
|
system_temp_loop_count_ = PushSystemTemp(true);
|
||||||
|
system_temp_grad_h_lod_ = PushSystemTemp(true);
|
||||||
|
system_temp_grad_v_ = PushSystemTemp(true);
|
||||||
if (is_vertex_shader()) {
|
if (is_vertex_shader()) {
|
||||||
system_temp_position_ = PushSystemTemp(true);
|
system_temp_position_ = PushSystemTemp(true);
|
||||||
} else if (is_pixel_shader()) {
|
} else if (is_pixel_shader()) {
|
||||||
|
@ -653,7 +658,9 @@ void DxbcShaderTranslator::CompleteShaderCode() {
|
||||||
// - system_temp_ps_pc_p0_a0_.
|
// - system_temp_ps_pc_p0_a0_.
|
||||||
// - system_temp_aL_.
|
// - system_temp_aL_.
|
||||||
// - system_temp_loop_count_.
|
// - system_temp_loop_count_.
|
||||||
PopSystemTemp(4);
|
// - system_temp_grad_h_lod_.
|
||||||
|
// - system_temp_grad_v_.
|
||||||
|
PopSystemTemp(6);
|
||||||
|
|
||||||
// Write stage-specific epilogue.
|
// Write stage-specific epilogue.
|
||||||
if (is_vertex_shader()) {
|
if (is_vertex_shader()) {
|
||||||
|
@ -2298,6 +2305,126 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction(
|
||||||
StoreResult(instr.result, system_temp_pv_, false);
|
StoreResult(instr.result, system_temp_pv_, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t DxbcShaderTranslator::FindOrAddTextureSRV(uint32_t fetch_constant,
|
||||||
|
TextureDimension dimension) {
|
||||||
|
// 1D and 2D textures (including stacked ones) are treated as 2D arrays for
|
||||||
|
// binding and coordinate simplicity.
|
||||||
|
if (dimension == TextureDimension::k1D) {
|
||||||
|
dimension = TextureDimension::k2D;
|
||||||
|
}
|
||||||
|
// 1 is added to the return value because T0/t0 is shared memory.
|
||||||
|
for (uint32_t i = 0; i < uint32_t(texture_srvs_.size()); ++i) {
|
||||||
|
const TextureSRV& texture_srv = texture_srvs_[i];
|
||||||
|
if (texture_srv.fetch_constant == fetch_constant &&
|
||||||
|
texture_srv.dimension == dimension) {
|
||||||
|
return 1 + i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TextureSRV new_texture_srv;
|
||||||
|
new_texture_srv.fetch_constant = fetch_constant;
|
||||||
|
new_texture_srv.dimension = dimension;
|
||||||
|
const char* dimension_name;
|
||||||
|
switch (dimension) {
|
||||||
|
case TextureDimension::k3D:
|
||||||
|
dimension_name = "3d";
|
||||||
|
break;
|
||||||
|
case TextureDimension::kCube:
|
||||||
|
dimension_name = "cube";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dimension_name = "2d";
|
||||||
|
}
|
||||||
|
new_texture_srv.name =
|
||||||
|
xe::format_string("xe_texture%u_%s", fetch_constant, dimension_name);
|
||||||
|
uint32_t srv_register = 1 + uint32_t(texture_srvs_.size());
|
||||||
|
texture_srvs_.push_back(new_texture_srv);
|
||||||
|
return srv_register;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DxbcShaderTranslator::ProcessTextureFetchInstruction(
|
||||||
|
const ParsedTextureFetchInstruction& instr) {
|
||||||
|
// TODO(Triang3l): Predicate.
|
||||||
|
|
||||||
|
bool store_result = false;
|
||||||
|
|
||||||
|
DxbcSourceOperand operand;
|
||||||
|
uint32_t operand_length = 0;
|
||||||
|
if (instr.operand_count >= 1) {
|
||||||
|
LoadDxbcSourceOperand(instr.operands[0], operand);
|
||||||
|
operand_length = DxbcSourceOperandLength(operand);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t tfetch_index = instr.operands[1].storage_index;
|
||||||
|
// Fetch constants are laid out like:
|
||||||
|
// tf0[0] tf0[1] tf0[2] tf0[3]
|
||||||
|
// tf0[4] tf0[5] tf1[0] tf1[1]
|
||||||
|
// tf1[2] tf1[3] tf1[4] tf1[5]
|
||||||
|
uint32_t tfetch_pair_offset = (tfetch_index >> 1) * 3;
|
||||||
|
|
||||||
|
// TODO(Triang3l): kTextureFetch, kGetTextureBorderColorFrac,
|
||||||
|
// kGetTextureComputedLod, kGetTextureGradients, kGetTextureWeights,
|
||||||
|
if (instr.opcode == FetchOpcode::kTextureFetch ||
|
||||||
|
instr.opcode == FetchOpcode::kGetTextureComputedLod) {
|
||||||
|
store_result = true;
|
||||||
|
|
||||||
|
uint32_t srv_register = FindOrAddTextureSRV(tfetch_index, instr.dimension);
|
||||||
|
// 3D or 2D stacked is selected dynamically.
|
||||||
|
uint32_t srv_register_3d;
|
||||||
|
if (instr.dimension == TextureDimension::k3D) {
|
||||||
|
srv_register_3d =
|
||||||
|
FindOrAddTextureSRV(tfetch_index, TextureDimension::k2D);
|
||||||
|
} else {
|
||||||
|
srv_register_3d = UINT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(Triang3l): Sampler, actually sample instead of this stub.
|
||||||
|
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MOV) |
|
||||||
|
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(8));
|
||||||
|
shader_code_.push_back(
|
||||||
|
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b1111, 1));
|
||||||
|
shader_code_.push_back(system_temp_pv_);
|
||||||
|
shader_code_.push_back(EncodeVectorSwizzledOperand(
|
||||||
|
D3D10_SB_OPERAND_TYPE_IMMEDIATE32, kSwizzleXYZW, 0));
|
||||||
|
shader_code_.push_back(0x3F800000);
|
||||||
|
shader_code_.push_back(0x3F800000);
|
||||||
|
shader_code_.push_back(0x3F800000);
|
||||||
|
shader_code_.push_back(0x3F800000);
|
||||||
|
++stat_.instruction_count;
|
||||||
|
++stat_.mov_instruction_count;
|
||||||
|
} else if (instr.opcode == FetchOpcode::kSetTextureLod) {
|
||||||
|
shader_code_.push_back(
|
||||||
|
ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MOV) |
|
||||||
|
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(3 + operand_length));
|
||||||
|
shader_code_.push_back(
|
||||||
|
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b1000, 1));
|
||||||
|
shader_code_.push_back(system_temp_grad_h_lod_);
|
||||||
|
UseDxbcSourceOperand(operand, kSwizzleXYZW, 0);
|
||||||
|
++stat_.instruction_count;
|
||||||
|
++stat_.mov_instruction_count;
|
||||||
|
} else if (instr.opcode == FetchOpcode::kSetTextureGradientsHorz ||
|
||||||
|
instr.opcode == FetchOpcode::kSetTextureGradientsVert) {
|
||||||
|
shader_code_.push_back(
|
||||||
|
ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MOV) |
|
||||||
|
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(3 + operand_length));
|
||||||
|
shader_code_.push_back(
|
||||||
|
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0111, 1));
|
||||||
|
shader_code_.push_back(instr.opcode == FetchOpcode::kSetTextureGradientsVert
|
||||||
|
? system_temp_grad_v_
|
||||||
|
: system_temp_grad_h_lod_);
|
||||||
|
UseDxbcSourceOperand(operand, kSwizzleXYZW);
|
||||||
|
++stat_.instruction_count;
|
||||||
|
++stat_.mov_instruction_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instr.operand_count >= 1) {
|
||||||
|
UnloadDxbcSourceOperand(operand);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (store_result) {
|
||||||
|
StoreResult(instr.result, system_temp_pv_, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DxbcShaderTranslator::ProcessVectorAluInstruction(
|
void DxbcShaderTranslator::ProcessVectorAluInstruction(
|
||||||
const ParsedAluInstruction& instr) {
|
const ParsedAluInstruction& instr) {
|
||||||
// TODO(Triang3l): Predicate.
|
// TODO(Triang3l): Predicate.
|
||||||
|
@ -4362,29 +4489,62 @@ void DxbcShaderTranslator::WriteResourceDefinitions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
// Bindings, in t#, cb# order
|
// Bindings, in s#, t#, cb# order
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
|
|
||||||
// Write used resource names, except for constant buffers because we have
|
// Write used resource names, except for constant buffers because we have
|
||||||
// their names already.
|
// their names already.
|
||||||
new_offset = (uint32_t(shader_object_.size()) - chunk_position_dwords) *
|
new_offset = (uint32_t(shader_object_.size()) - chunk_position_dwords) *
|
||||||
sizeof(uint32_t);
|
sizeof(uint32_t);
|
||||||
|
uint32_t sampler_name_offset = new_offset;
|
||||||
|
for (uint32_t i = 0; i < uint32_t(sampler_bindings_.size()); ++i) {
|
||||||
|
new_offset +=
|
||||||
|
AppendString(shader_object_, sampler_bindings_[i].name.c_str());
|
||||||
|
}
|
||||||
uint32_t shared_memory_name_offset = new_offset;
|
uint32_t shared_memory_name_offset = new_offset;
|
||||||
new_offset += AppendString(shader_object_, "xe_shared_memory");
|
new_offset += AppendString(shader_object_, "xe_shared_memory");
|
||||||
// TODO(Triang3l): Texture and sampler names.
|
uint32_t texture_name_offset = new_offset;
|
||||||
|
for (uint32_t i = 0; i < uint32_t(texture_srvs_.size()); ++i) {
|
||||||
|
new_offset += AppendString(shader_object_, texture_srvs_[i].name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
// Write the offset to the header.
|
// Write the offset to the header.
|
||||||
shader_object_[chunk_position_dwords + 3] = new_offset;
|
shader_object_[chunk_position_dwords + 3] = new_offset;
|
||||||
|
|
||||||
|
// Samplers.
|
||||||
|
for (uint32_t i = 0; i < uint32_t(sampler_bindings_.size()); ++i) {
|
||||||
|
const SamplerBinding& sampler_binding = sampler_bindings_[i];
|
||||||
|
shader_object_.push_back(sampler_name_offset);
|
||||||
|
// D3D_SIT_SAMPLER.
|
||||||
|
shader_object_.push_back(3);
|
||||||
|
// No D3D_RESOURCE_RETURN_TYPE.
|
||||||
|
shader_object_.push_back(0);
|
||||||
|
// D3D_SRV_DIMENSION_UNKNOWN (not an SRV).
|
||||||
|
shader_object_.push_back(0);
|
||||||
|
// Multisampling not applicable.
|
||||||
|
shader_object_.push_back(0);
|
||||||
|
// Register s[i].
|
||||||
|
shader_object_.push_back(i);
|
||||||
|
// One binding.
|
||||||
|
shader_object_.push_back(1);
|
||||||
|
// No D3D_SHADER_INPUT_FLAGS.
|
||||||
|
shader_object_.push_back(0);
|
||||||
|
// Register space 0.
|
||||||
|
shader_object_.push_back(0);
|
||||||
|
// Sampler ID S[i].
|
||||||
|
shader_object_.push_back(i);
|
||||||
|
sampler_name_offset += GetStringLength(sampler_binding.name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
// Shared memory.
|
// Shared memory.
|
||||||
shader_object_.push_back(shared_memory_name_offset);
|
shader_object_.push_back(shared_memory_name_offset);
|
||||||
// D3D_SIT_BYTEADDRESS.
|
// D3D_SIT_BYTEADDRESS.
|
||||||
shader_object_.push_back(7);
|
shader_object_.push_back(7);
|
||||||
// D3D_RETURN_TYPE_MIXED.
|
// D3D_RETURN_TYPE_MIXED.
|
||||||
shader_object_.push_back(6);
|
shader_object_.push_back(6);
|
||||||
// D3D_SRV_DIMENSION_UNKNOWN.
|
// D3D_SRV_DIMENSION_BUFFER.
|
||||||
shader_object_.push_back(1);
|
shader_object_.push_back(1);
|
||||||
// Not multisampled.
|
// Multisampling not applicable.
|
||||||
shader_object_.push_back(0);
|
shader_object_.push_back(0);
|
||||||
// Register t0.
|
// Register t0.
|
||||||
shader_object_.push_back(0);
|
shader_object_.push_back(0);
|
||||||
|
@ -4397,7 +4557,40 @@ void DxbcShaderTranslator::WriteResourceDefinitions() {
|
||||||
// SRV ID T0.
|
// SRV ID T0.
|
||||||
shader_object_.push_back(0);
|
shader_object_.push_back(0);
|
||||||
|
|
||||||
// TODO(Triang3l): Textures and samplers.
|
for (uint32_t i = 0; i < uint32_t(texture_srvs_.size()); ++i) {
|
||||||
|
const TextureSRV& texture_srv = texture_srvs_[i];
|
||||||
|
shader_object_.push_back(texture_name_offset);
|
||||||
|
// D3D_SIT_TEXTURE.
|
||||||
|
shader_object_.push_back(2);
|
||||||
|
// D3D_RETURN_TYPE_FLOAT.
|
||||||
|
shader_object_.push_back(5);
|
||||||
|
switch (texture_srv.dimension) {
|
||||||
|
case TextureDimension::k3D:
|
||||||
|
// D3D_SRV_DIMENSION_TEXTURE3D.
|
||||||
|
shader_object_.push_back(8);
|
||||||
|
break;
|
||||||
|
case TextureDimension::kCube:
|
||||||
|
// D3D_SRV_DIMENSION_TEXTURECUBE.
|
||||||
|
shader_object_.push_back(9);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// D3D_SRV_DIMENSION_TEXTURE2DARRAY.
|
||||||
|
shader_object_.push_back(5);
|
||||||
|
}
|
||||||
|
// Not multisampled.
|
||||||
|
shader_object_.push_back(0xFFFFFFFFu);
|
||||||
|
// Register t[1 + i] - t0 is shared memory.
|
||||||
|
shader_object_.push_back(1 + i);
|
||||||
|
// One binding.
|
||||||
|
shader_object_.push_back(1);
|
||||||
|
// D3D_SIF_TEXTURE_COMPONENTS (4-component).
|
||||||
|
shader_object_.push_back(0xC);
|
||||||
|
// Register space 0.
|
||||||
|
shader_object_.push_back(0);
|
||||||
|
// SRV ID T[1 + i] - T0 is shared memory.
|
||||||
|
shader_object_.push_back(1 + i);
|
||||||
|
texture_name_offset += GetStringLength(texture_srv.name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
// Constant buffers.
|
// Constant buffers.
|
||||||
for (uint32_t i = 0; i < uint32_t(RdefConstantBufferIndex::kCount); ++i) {
|
for (uint32_t i = 0; i < uint32_t(RdefConstantBufferIndex::kCount); ++i) {
|
||||||
|
@ -4409,6 +4602,7 @@ void DxbcShaderTranslator::WriteResourceDefinitions() {
|
||||||
shader_object_.push_back(0);
|
shader_object_.push_back(0);
|
||||||
// D3D_SRV_DIMENSION_UNKNOWN (not an SRV).
|
// D3D_SRV_DIMENSION_UNKNOWN (not an SRV).
|
||||||
shader_object_.push_back(0);
|
shader_object_.push_back(0);
|
||||||
|
// Multisampling not applicable.
|
||||||
shader_object_.push_back(0);
|
shader_object_.push_back(0);
|
||||||
shader_object_.push_back(uint32_t(cbuffer.register_index));
|
shader_object_.push_back(uint32_t(cbuffer.register_index));
|
||||||
shader_object_.push_back(cbuffer.binding_count);
|
shader_object_.push_back(cbuffer.binding_count);
|
||||||
|
@ -4416,6 +4610,7 @@ void DxbcShaderTranslator::WriteResourceDefinitions() {
|
||||||
shader_object_.push_back(cbuffer.user_packed ? 1 : 0);
|
shader_object_.push_back(cbuffer.user_packed ? 1 : 0);
|
||||||
// Register space 0.
|
// Register space 0.
|
||||||
shader_object_.push_back(0);
|
shader_object_.push_back(0);
|
||||||
|
// CBV ID CB[i].
|
||||||
shader_object_.push_back(i);
|
shader_object_.push_back(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4680,7 +4875,9 @@ void DxbcShaderTranslator::WriteShaderCode() {
|
||||||
shader_object_.push_back(EncodeVectorSwizzledOperand(
|
shader_object_.push_back(EncodeVectorSwizzledOperand(
|
||||||
D3D10_SB_OPERAND_TYPE_CONSTANT_BUFFER, kSwizzleXYZW, 3));
|
D3D10_SB_OPERAND_TYPE_CONSTANT_BUFFER, kSwizzleXYZW, 3));
|
||||||
shader_object_.push_back(cbuffer_index);
|
shader_object_.push_back(cbuffer_index);
|
||||||
|
// Lower register bound in the space.
|
||||||
shader_object_.push_back(uint32_t(cbuffer.register_index));
|
shader_object_.push_back(uint32_t(cbuffer.register_index));
|
||||||
|
// Upper register bound in the space.
|
||||||
shader_object_.push_back(uint32_t(cbuffer.register_index) +
|
shader_object_.push_back(uint32_t(cbuffer.register_index) +
|
||||||
cbuffer.binding_count - 1);
|
cbuffer.binding_count - 1);
|
||||||
shader_object_.push_back((cbuffer.size + 15) >> 4);
|
shader_object_.push_back((cbuffer.size + 15) >> 4);
|
||||||
|
@ -4688,6 +4885,21 @@ void DxbcShaderTranslator::WriteShaderCode() {
|
||||||
shader_object_.push_back(0);
|
shader_object_.push_back(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Samplers.
|
||||||
|
for (uint32_t i = 0; i < uint32_t(sampler_bindings_.size()); ++i) {
|
||||||
|
const SamplerBinding& sampler_binding = sampler_bindings_[i];
|
||||||
|
shader_object_.push_back(
|
||||||
|
ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_DCL_SAMPLER) |
|
||||||
|
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(6) |
|
||||||
|
ENCODE_D3D10_SB_SAMPLER_MODE(D3D10_SB_SAMPLER_MODE_DEFAULT));
|
||||||
|
shader_object_.push_back(EncodeVectorSwizzledOperand(
|
||||||
|
D3D10_SB_OPERAND_TYPE_SAMPLER, kSwizzleXYZW, 3));
|
||||||
|
shader_object_.push_back(i);
|
||||||
|
shader_object_.push_back(i);
|
||||||
|
shader_object_.push_back(i);
|
||||||
|
shader_object_.push_back(0);
|
||||||
|
}
|
||||||
|
|
||||||
// Shader resources.
|
// Shader resources.
|
||||||
// Shared memory ByteAddressBuffer (T0, at t0, space0).
|
// Shared memory ByteAddressBuffer (T0, at t0, space0).
|
||||||
shader_object_.push_back(
|
shader_object_.push_back(
|
||||||
|
@ -4700,6 +4912,39 @@ void DxbcShaderTranslator::WriteShaderCode() {
|
||||||
shader_object_.push_back(0);
|
shader_object_.push_back(0);
|
||||||
shader_object_.push_back(0);
|
shader_object_.push_back(0);
|
||||||
|
|
||||||
|
// Textures.
|
||||||
|
for (uint32_t i = 0; i < uint32_t(texture_srvs_.size()); ++i) {
|
||||||
|
const TextureSRV& texture_srv = texture_srvs_[i];
|
||||||
|
D3D10_SB_RESOURCE_DIMENSION texture_srv_dimension;
|
||||||
|
switch (texture_srv.dimension) {
|
||||||
|
case TextureDimension::k3D:
|
||||||
|
texture_srv_dimension = D3D10_SB_RESOURCE_DIMENSION_TEXTURE3D;
|
||||||
|
break;
|
||||||
|
case TextureDimension::kCube:
|
||||||
|
texture_srv_dimension = D3D10_SB_RESOURCE_DIMENSION_TEXTURECUBE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
texture_srv_dimension = D3D10_SB_RESOURCE_DIMENSION_TEXTURE2DARRAY;
|
||||||
|
}
|
||||||
|
shader_object_.push_back(
|
||||||
|
ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_DCL_RESOURCE) |
|
||||||
|
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(7) |
|
||||||
|
ENCODE_D3D10_SB_RESOURCE_DIMENSION(texture_srv_dimension));
|
||||||
|
shader_object_.push_back(EncodeVectorSwizzledOperand(
|
||||||
|
D3D10_SB_OPERAND_TYPE_RESOURCE, kSwizzleXYZW, 3));
|
||||||
|
// T0 is shared memory.
|
||||||
|
shader_object_.push_back(1 + i);
|
||||||
|
// t0 is shared memory.
|
||||||
|
shader_object_.push_back(1 + i);
|
||||||
|
shader_object_.push_back(1 + i);
|
||||||
|
shader_object_.push_back(
|
||||||
|
ENCODE_D3D10_SB_RESOURCE_RETURN_TYPE(D3D10_SB_RETURN_TYPE_FLOAT, 0) |
|
||||||
|
ENCODE_D3D10_SB_RESOURCE_RETURN_TYPE(D3D10_SB_RETURN_TYPE_FLOAT, 1) |
|
||||||
|
ENCODE_D3D10_SB_RESOURCE_RETURN_TYPE(D3D10_SB_RETURN_TYPE_FLOAT, 2) |
|
||||||
|
ENCODE_D3D10_SB_RESOURCE_RETURN_TYPE(D3D10_SB_RETURN_TYPE_FLOAT, 3));
|
||||||
|
shader_object_.push_back(0);
|
||||||
|
}
|
||||||
|
|
||||||
// Inputs and outputs.
|
// Inputs and outputs.
|
||||||
if (is_vertex_shader()) {
|
if (is_vertex_shader()) {
|
||||||
// Unswapped vertex index input (only X component).
|
// Unswapped vertex index input (only X component).
|
||||||
|
|
|
@ -10,8 +10,11 @@
|
||||||
#ifndef XENIA_GPU_DXBC_SHADER_TRANSLATOR_H_
|
#ifndef XENIA_GPU_DXBC_SHADER_TRANSLATOR_H_
|
||||||
#define XENIA_GPU_DXBC_SHADER_TRANSLATOR_H_
|
#define XENIA_GPU_DXBC_SHADER_TRANSLATOR_H_
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "xenia/base/math.h"
|
||||||
#include "xenia/gpu/shader_translator.h"
|
#include "xenia/gpu/shader_translator.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
@ -59,6 +62,30 @@ class DxbcShaderTranslator : public ShaderTranslator {
|
||||||
uint32_t color_output_map[4];
|
uint32_t color_output_map[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TextureSRV {
|
||||||
|
uint32_t fetch_constant;
|
||||||
|
TextureDimension dimension;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
// The first binding returned is at t1 because t0 is shared memory.
|
||||||
|
const TextureSRV* GetTextureSRVs(uint32_t& count_out) const {
|
||||||
|
count_out = uint32_t(texture_srvs_.size());
|
||||||
|
return texture_srvs_.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SamplerBinding {
|
||||||
|
uint32_t fetch_constant;
|
||||||
|
TextureFilter mag_filter;
|
||||||
|
TextureFilter min_filter;
|
||||||
|
TextureFilter mip_filter;
|
||||||
|
AnisoFilter aniso_filter;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
const SamplerBinding* GetSamplerBindings(uint32_t& count_out) const {
|
||||||
|
count_out = uint32_t(sampler_bindings_.size());
|
||||||
|
return sampler_bindings_.data();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void Reset() override;
|
void Reset() override;
|
||||||
|
|
||||||
|
@ -68,6 +95,8 @@ class DxbcShaderTranslator : public ShaderTranslator {
|
||||||
|
|
||||||
void ProcessVertexFetchInstruction(
|
void ProcessVertexFetchInstruction(
|
||||||
const ParsedVertexFetchInstruction& instr) override;
|
const ParsedVertexFetchInstruction& instr) override;
|
||||||
|
void ProcessTextureFetchInstruction(
|
||||||
|
const ParsedTextureFetchInstruction& instr) override;
|
||||||
void ProcessAluInstruction(const ParsedAluInstruction& instr) override;
|
void ProcessAluInstruction(const ParsedAluInstruction& instr) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -272,11 +301,20 @@ class DxbcShaderTranslator : public ShaderTranslator {
|
||||||
// Emits copde for endian swapping of the data located in pv.
|
// Emits copde for endian swapping of the data located in pv.
|
||||||
void SwapVertexData(uint32_t vfetch_index, uint32_t write_mask);
|
void SwapVertexData(uint32_t vfetch_index, uint32_t write_mask);
|
||||||
|
|
||||||
|
// Returns T#/t# index (they are the same in this translator).
|
||||||
|
uint32_t FindOrAddTextureSRV(uint32_t fetch_constant,
|
||||||
|
TextureDimension dimension);
|
||||||
|
|
||||||
void ProcessVectorAluInstruction(const ParsedAluInstruction& instr);
|
void ProcessVectorAluInstruction(const ParsedAluInstruction& instr);
|
||||||
void ProcessScalarAluInstruction(const ParsedAluInstruction& instr);
|
void ProcessScalarAluInstruction(const ParsedAluInstruction& instr);
|
||||||
|
|
||||||
// Appends a string to a DWORD stream, returns the DWORD-aligned length.
|
// Appends a string to a DWORD stream, returns the DWORD-aligned length.
|
||||||
static uint32_t AppendString(std::vector<uint32_t>& dest, const char* source);
|
static uint32_t AppendString(std::vector<uint32_t>& dest, const char* source);
|
||||||
|
// Returns the length of a string as if it was appended to a DWORD stream, in
|
||||||
|
// bytes.
|
||||||
|
static inline uint32_t GetStringLength(const char* source) {
|
||||||
|
return uint32_t(xe::align(std::strlen(source) + 1, sizeof(uint32_t)));
|
||||||
|
}
|
||||||
|
|
||||||
void WriteResourceDefinitions();
|
void WriteResourceDefinitions();
|
||||||
void WriteInputSignature();
|
void WriteInputSignature();
|
||||||
|
@ -418,6 +456,9 @@ class DxbcShaderTranslator : public ShaderTranslator {
|
||||||
// Loop counter stack, .x is the active loop. Represents number of times
|
// Loop counter stack, .x is the active loop. Represents number of times
|
||||||
// remaining to loop.
|
// remaining to loop.
|
||||||
uint32_t system_temp_loop_count_;
|
uint32_t system_temp_loop_count_;
|
||||||
|
// Explicitly set texture gradients and LOD.
|
||||||
|
uint32_t system_temp_grad_h_lod_;
|
||||||
|
uint32_t system_temp_grad_v_;
|
||||||
|
|
||||||
// Position in vertex shaders (because viewport and W transformations can be
|
// Position in vertex shaders (because viewport and W transformations can be
|
||||||
// applied in the end of the shader).
|
// applied in the end of the shader).
|
||||||
|
@ -429,6 +470,9 @@ class DxbcShaderTranslator : public ShaderTranslator {
|
||||||
|
|
||||||
bool writes_depth_;
|
bool writes_depth_;
|
||||||
|
|
||||||
|
std::vector<TextureSRV> texture_srvs_;
|
||||||
|
std::vector<SamplerBinding> sampler_bindings_;
|
||||||
|
|
||||||
// The STAT chunk (based on Wine d3dcompiler_parse_stat).
|
// The STAT chunk (based on Wine d3dcompiler_parse_stat).
|
||||||
struct Statistics {
|
struct Statistics {
|
||||||
uint32_t instruction_count;
|
uint32_t instruction_count;
|
||||||
|
|
Loading…
Reference in New Issue